我遇到了同样的问题,这就是我所做的。
回调助手
// The Callbacks module.
//
// A simple way of managing a collection of callbacks
// and executing them at a later point in time, using jQuery's
// `Deferred` object.
//
// Source: https://github.com/derickbailey/backbone.marionette/blob/master/lib/backbone.marionette.js#L1291
define(['jquery'], function($) {
function Callbacks() {
this.deferred = $.Deferred();
this.promise = this.deferred.promise();
}
Callbacks.prototype = {
constructor: Callbacks,
// Add a callback to be executed. Callbacks added here are
// guaranteed to execute, even if they are added after the
// `run` method is called.
add: function(callback, contextOverride) {
this.promise.done(function(context, options) {
if (contextOverride) {
context = contextOverride;
}
callback.call(context, options);
});
},
// Run all registered callbacks with the context specified.
// Additional callbacks can be added after this has been run
// and they will still be executed.
run: function(options, context) {
this.deferred.resolve(context, options);
}
};
return Callbacks;
});
核心合集
在这个集合中,我们有 2 个重要的方法:onReset() 和 collectionReset()。 onReset() 方法应该是 Views“监听”集合的 reset 事件的方式,因为它使用 Promises。
collectionReset() 方法仅在集合的 reset 事件被触发时执行,此时我们认为集合已加载并且我们解析所有添加的回调.
这会处理竞争条件,因为回调是使用 onReset() 方法添加的,即使在添加回调之前触发了事件时也会执行。
当你创建一个新集合并让它继承这个集合时,你必须确保在获取时添加reset选项:(new ExampleCollection()).fetch({ reset: true })
// The Core Collection - other collections inherit from this one.
// Source: http://lostechies.com/derickbailey/2012/02/03/get-a-model-from-a-backbone-collection-without-knowing-if-the-collection-is-loaded
define([
'jquery',
'backbone',
'app/callbacks'
], function($, Backbone, Callbacks) {
var CoreCollection = Backbone.Collection.extend({
constructor: function() {
Backbone.Collection.prototype.constructor.apply(this, [].slice.call(arguments));
this.onResetCallbacks = new Callbacks();
this.on('reset', this.collectionReset, this);
},
// The `onReset` method should be called by views to render collection data
// when the particular collection has been loaded from the server.
onReset: function(callback, contextOverride) {
this.onResetCallbacks.add(callback, contextOverride);
if (this.loaded) {
this.onResetCallbacks.run(this);
}
},
// Since this method is called only on the collection's `reset`
// event, we assume that the collection has been fully loaded.
collectionReset: function() {
if (!this.loaded) {
this.loaded = true;
}
// Execute all the `onResetCallbacks` callbacks.
this.onResetCallbacks.run(this);
}
});
return CoreCollection;
});
示例视图
在示例视图中,您将执行以下操作:
define([
'jquery',
'backbone',
'handlebars',
],
function($, Backbone, Handlebars) {
var ExampleView = Backbone.View.extend({
id: 'example-view',
template: Handlebars.templates.example,
events: {
},
initialize: function() {
// If it renders a collection from the server.
this.collection = __collection_name__;
this.collection.onReset(function() {
// It's guaranteed to execute.
// No race condition anymore!
// ...
});
}
});
return ExampleView;
});