Backbone.Collection fetch的竞争条件

时间:2014-06-03 08:17:25

标签: javascript backbone.js underscore.js

我在选定的月份生成日期列表,对于每个日期,我都会进行Backbone.Collection抓取。

以下是我如何循环一个月中的每个日期

for (var i = 1; i <= numOfDays; i++) {
   var d = i < 10 ? '0'+i:i;
   var v = new View({
      dt: this.year + this.month + (d),
      param: this.array
   });      
   this.$el.append(v.render().el);
}

如上所示,每个视图(backbone.view)都代表dateparam object。然后我在callin render()

上使用 UnderscoreJs param方法循环_.each对象
_.each(this.param, this.reading, this);

稍后它会启动backbone.collection的新对象并立即执行获取

reading: function (value, key) {
   var _this = this;
   this.fetchData(new Data.Collection(), '/api/ + value.ipid').done(function(coll) {
      var input = $('<input>').val(value.ipid).attr('data-inid', coll.first().get('in_id'));
      _this.$el.append(input);
   });
}

我将这个函数this.fetchData分开了

fetchData: function (obj, url) {
    var deferred = $.Deferred(),
        collection = obj;           
    collection.url = url;
    var xhr = collection.fetch().done(function(data, textStatus, jqXHR) {
        deferred.resolve(collection, data, textStatus, jqXHR);
    }).fail(deferred.reject);
    var promise = deferred.promise();
    promise.abort = _.bind(xhr.abort, xhr);
    return promise;     
}

不幸的是,对于每个视图param对象中的项目的顺序将会改变,因为它取决于backbone.ajax的竞争条件。让我们看看param对象

的项目
[{ipid: 44, measure: "cumec"},{ipid: 45, measure: "meter"},{ipid: 46, measure: "milimeter"}{ipid: 47, measure: "cumec"}]

对象项目的顺序正确。 44,45,46和47.但是,为了获得我们最初通过的列表,它将在获取操作后更改。

如何在开始循环param对象中的另一个项目

之前,告诉backbonejs或underscorejs等待每个提取操作完成

我只想让循环( _。每个)在继续循环之前等待获取操作完成

希望有人可以启发实现这一目标的方法。谢谢你,祝你有个美好的一天

2 个答案:

答案 0 :(得分:1)

如果在视图创建时创建并附加DOM元素(即在reading函数内),则从完成回调内部引用,元素的顺序与param数组内的顺序相同。 / p>

附注:您可以直接使用url实例化collection,并且不需要围绕fetch返回的承诺包装另一个jQuery承诺。

答案 1 :(得分:0)

我认为您的问题的解决方案是使用the iterator provided by Async.js library,因此您的代码将如下所示:

async.eachSeries(this.param, _.bind(this.reading, this), yourCallbackWhenTheArrayIsFinished);

reading: function (value, callback) {
   var _this = this;
   this.fetchData(new Data.Collection(), '/api/ + value.ipid').done(function(coll) {
      var input = $('<input>').val(value.ipid).attr('data-inid', coll.first().get('in_id'));
      _this.$el.append(input);
      callback();
   });
}

因此,在从done处理程序调用callback()之前,eachSeries不会处理下一个元素