Javascript 主干模型:解析覆盖中的Ajax请求

Javascript 主干模型:解析覆盖中的Ajax请求,javascript,jquery,ajax,backbone.js,backbone-model,Javascript,Jquery,Ajax,Backbone.js,Backbone Model,我有一个场景,模型的fetch()调用将返回一个属性需要从中传递到另一个API的数据,该API的返回类型将是实际需要的数据 var Issue = Backbone.Model.extend({ urlRoot: 'https://api.github.com/repos/ibrahim-islam/ibrahim-islam.github.io/issues', parse: function(response, options){ var markdown =

我有一个场景,模型的
fetch()
调用将返回一个属性需要从中传递到另一个API的数据,该API的返回类型将是实际需要的数据

var Issue = Backbone.Model.extend({
    urlRoot: 'https://api.github.com/repos/ibrahim-islam/ibrahim-islam.github.io/issues',
    parse: function(response, options){
        var markdown = new Markdown({ text : response.body });
        markdown.fetch({
            contentType: 'application/json',
            type: 'POST',
            data: JSON.stringify( markdown.toJSON() ),
            success: function(data){
                response.body = data;
            }
        });
        return response;
    }
});

var Markdown = Backbone.Model.extend({
    defaults:{
        'text': '',
        'mode' : 'markdown'
    },
    url: 'https://api.github.com/markdown'
});
因此,当提取
问题时

var issue = new Issue({id: 1});
issue.fetch().then(function(){
  //do stuff
});
它将有一个
body
属性,其中包含标记语法文本,我需要将该文本传递给另一个API,并获取将传递给view的响应

从上面可以看出,我尝试重写
parse
,但是它的返回类型必须是一个对象,
fetch
将是
async
,那么我在这里可以做些什么来实现这一点呢


注意:我知道在服务器中聚合数据,然后接收数据是最好的主意,但这是不可能的。

我认为您必须覆盖模型的
获取
,才能使其正常工作

请考虑默认提取的外观:

fetch: function(options) {
  options = _.extend({parse: true}, options);
  var model = this;
  var success = options.success;
  options.success = function(resp) {
    var serverAttrs = options.parse ? model.parse(resp, options) : resp;
    if (!model.set(serverAttrs, options)) return false;
    if (success) success.call(options.context, model, resp, options);
    model.trigger('sync', model, resp, options);
  };
  wrapError(this, options);
  return this.sync('read', this, options);
},
()

该实现不支持异步版本的
model.parse
,但由于您使用
.extend
创建了一个模型类,因此您可以使用自己的实现覆盖它,让我们看看它的功能。它接受一个
选项
对象,创建一个
成功
回调,然后委托给
主干.Sync

正是这个回调调用了
parse
,这就是支持异步所需要做的

最快、最肮脏的方法可能是复制和修改现有的默认获取

var MyModel = Backbone.Model.extend({

    fetch: function(options) {
      options = _.extend({parse: true}, options);
      var model = this;
      var success = options.success;
      options.success = function(resp) {

        function parser(resp, options, cb) {
           ...do your async request stuff and call cb with the result when done...
        }

        parser(resp, options, function(result) {
            if (!model.set(result, options)) return false;
            if (success) success.call(options.context, model, resp, options);
            model.trigger('sync', model, resp, options);
        });

      };
      wrapError(this, options);
      return this.sync('read', this, options);
    }

});
这只是一个例子,你可以尝试解决这个问题。我还没有测试过它,它可能不起作用,但我看不到任何明显的理由说明它不应该起作用。

您可以覆盖
问题中的
模型来链接您的请求

var Issue = Backbone.Model.extend({
    urlRoot: 'https://api.github.com/repos/ibrahim-islam/ibrahim-islam.github.io/issues',

    sync: function(method, model, options) {
        if (method !== 'read')
            return Backbone.sync.apply(this, arguments);

        // first request
        var xhr = Backbone.ajax({
            type: 'GET', 
            dataType: 'json',
            url: _.result(model, 'url')
        });

        // second request
        return xhr.then(function (resp1) {
            var markdown = new Markdown({text : resp1.body || 'body'});
            var data = markdown.toJSON();

            // the callback to fill your model, will call parse
            var success = options.success;

            return Backbone.ajax({
                url: _.result(markdown, 'url'),
                dataType: 'html',
                contentType: 'application/json',
                type: 'POST',
                data: data
            }).then(function(resp2) {
                // sets the data you need from the response
                var resp = _.extend({}, resp1, {
                    body: resp2
                });

                // fills the model and triggers the sync event
                success(resp);

                // transformed value returned by the promise
                return resp;
            });
        });
    }
});
传递到
Model.sync
的选项散列包含对
Model.parse
的回调,当您对数据感到满意时,可以使用它设置模型上的属性


还有一个演示

JSON.stringify(markdown.toJSON())
-那将是双重编码,你确定要这样吗?@Tomalak只有在我的请求通过之后。但我会再试一次。谢谢你的提醒。这似乎比我的建议好+1从我这里。@Nikosh我需要主对象和标记解析结果,以便替换
body
属性。请看这张小提琴:@lbrahim我不知怎么错过了第二个请求返回的是HTML而不是JSON。更新