Backbone Model:解析覆盖中的Ajax请求

时间:2015-07-28 10:54:23

标签: 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 = 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'
});

因此,当提取Issue时:

var issue = new Issue({id: 1});
issue.fetch().then(function(){
  //do stuff
});

它将具有包含markdown语法文本的body属性,而我需要将其传递给另一个API并获取将传递给查看的响应。

从上面可以看出,我尝试覆盖parse,但其返回类型必须是一个对象,而fetch将是async所以我可以在此处做些什么来完成这项工作?

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

2 个答案:

答案 0 :(得分:4)

您可以覆盖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; }); }); } }); 模型中的sync method来链接您的请求。

Model.sync

传递给model.parse的选项哈希包含{{1}}的回调,当您对数据感到满意时,可以使用它来设置模型的属性。

演示http://jsfiddle.net/puwueqe3/5/

答案 1 :(得分:2)

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

考虑默认提取的内容:

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);
},

github

该实现不支持model.parse的异步版本,但由于您使用.extend创建了一个模型类,因此您可以使用自己的实现来覆盖它,所以让我们看看它的作用。它需要options个对象,创建success回调,然后委托给Backbone.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);
    }

});

这只是您尝试解决此问题的一个示例。我没有测试它,它可能无法工作,但我没有看到任何明显的原因,为什么它不应该。