我希望能够使用jQuery的Deferred对象来操作通过Backbone Collections和Models加载数据。有没有什么办法可以修改提供给完成和失败回调的参数来包含Model或Collection实例?我想象的是以下内容:
var _sync = Backbone.sync;
Backbone.sync = function() {
var jqXhr = _sync.apply(this, arguments);
var self = this;
return jqXhr.pipe(function() {
var cbArgs = [self];
cbArgs.push.apply(cbArgs, arguments);
return cbArgs;
}
}
...
var c = new Backbone.Collection();
c.url = "/path/to/resources";
c.fetch().then(function(collection, data, textStatus, jqXhr) {
// do stuff with collection
});
当然,由于filter返回一个数组,因此使用数组而不是枚举参数调用done回调。据我所知,管道只能修改提供的参数,而不能添加。任何建议将不胜感激。
编辑:这是一个非常简化的例子;因为在原始集合上创建了一个闭包,所以我可以对它进行操作。但是,用例是多个Backbone Views可能依赖于被提取的相同数据,所以我希望能够只为这些视图提供jQuery Deferred对象,而不是Deferred和collection实例。
另一个编辑:在下面发布了一个解决方案,但欢迎任何其他建议。
答案 0 :(得分:2)
我发现我可以通过让.pipe方法返回一个新的$ .Deferred来实现这个目的,并使用修改过的参数立即解析:
var _sync = Backbone.sync;
Backbone.sync = function() {
var jqXhr = _sync.apply(this, arguments);
var self = this;
var deferred = jqXhr.pipe(function() {
var cbArgs = [self];
cbArgs.push.apply(cbArgs, arguments);
var deferred = new $.Deferred();
return deferred.resolve.apply(deferred, cbArgs);
});
return $.extend(true, jqXhr, deferred);
};
答案 1 :(得分:1)
一个非常类似于你的答案的解决方案,但没有管道,因为你实际上并不需要过滤结果:我直接从Backbone.sync返回一个新的延迟而不是管道已解决的延迟
Backbone.originalSync = Backbone.sync;
Backbone.sync = function(method, model, options) {
var xhr = Backbone.originalSync.call(this, method, model, options);
var dfd = $.Deferred();
xhr.done(function() {
var cbArgs = [model].concat(_.toArray(arguments));
dfd.resolve.apply(dfd, cbArgs);
});
xhr.fail(function() {
var cbArgs = [model].concat(_.toArray(arguments));
dfd.reject.apply(dfd, cbArgs);
});
return dfd;
};
如果您愿意将this
绑定到回调中的模型/集合,这会使函数签名保持不变,这是一个更简单的变体:
Backbone.originalSync = Backbone.sync;
Backbone.sync = function(method, model, options) {
var xhr = Backbone.originalSync.call(this, method, model, options);
var dfd = $.Deferred();
xhr.done(function() {
dfd.resolveWith(model, arguments);
});
xhr.fail(function() {
dfd.rejectWith(model, arguments);
});
return dfd;
};
var c=new Backbone.Collection();
c.fetch().done(function() {
console.log(this);
console.log(arguments);
});
这导致我们将模型作为上下文传递给Ajax请求:
Backbone.originalSync = Backbone.sync;
Backbone.sync = function(method, model, options) {
options || (options={}) ;
options.context = model;
return Backbone.originalSync.call(this, method, model, options);
};
var c=new Backbone.Collection();
c.fetch().done(function() {
console.log(this);
});