我有可变数量的$.Deferred()
个对象被推入数组以便通过$.when()
执行。使用elsewhere on Stack Overflow中的建议,我决定采用手工编码的$.when.all([$.Deferred(), ...])
方法。
具体而言,$.Deferred()
对象包含一个函数,该函数对每个对象执行一个indexedDB .put()
。我希望它们在调用$.when.all()
时完成,并在其中执行相应的.then()
函数中的代码,但我通过断点发现它在调用时立即执行.put()
,并且javascript的执行将.then()
函数全部绕过,然后继续。
var putQueryArray = [];
_.each(favorites, function(fav) { // favorites being an array of updated indexedDB .get()s
var objectStore = db.transaction(['store'], 'readwrite') // var db defined elsewhere
.objectStore('store');
putQueryArray.push($.Deferred(function() {
var update = objectStore.put(fav); // This executes immediately, as verified in Chrome's Resources tab
update.onsuccess = _.bind(function(e) {
this.resolve(e); // Even if I put a breakpoint here, it never triggers
}, this);
update.onerror = _.bind(function(e) {
this.reject(e);
}, this);
}).promise());
});
// It appears this is ignored all together
$.when.all(putQueryArray).then(function(res) { // I (think I) expect this line to execute the above array of $.Deferred()'s?
//This function never executes
}, function(err) { ... });
我已经尝试了一切,因为没有将整个函数包装在$.Deferred(function() { ... });
中,而是在函数中调用$ .Deferred作为变量并返回其承诺,将.promise()
部分全部排除在一起,这两者都导致它实际执行.then()
函数,但实际上并没有执行.put()
。我在上面的代码中做错了什么?
答案 0 :(得分:2)
answer where you discovered jQuery.when.all()
在使用之前定义了该方法。换句话说,jQuery.when.all()
是一种自定义的,而不是本机的jQuery方法。
它的设计目的是克服jQuery.when()
的良好理解和良好容忍的问题,它只接受离散的承诺作为参数,而不是承诺数组。
这不是一个大问题的原因是因为javascript的本地Function.prototype.apply允许使用参数数组来代替离散参数调用任何函数(并且thisArg
为jQuery.when.all()
被指定)。
事实上,如果你仔细阅读了你发现自定义方法的答案,那么你会发现它正是它为你做的。
完全不使用$.when.apply(null, putQueryArray).then(function(res) {
...
}, function(err) {
...
});
,你会写:
$.when.apply($, putQueryArray)
许多人选择撰写thisArg
,但第一个参数$.when
未被null
使用,而$.when.all()
就足够了。
理解了所有这些并putQueryArray.push($.Deferred(function(dfrd) { // `dfrd` is a reference to the Deferred that will be returned
var update = objectStore.put(fav);
// `dfrd.resolve` and `dfrd.reject` both have `dfrd` already bound in, so .bind() is not required.
update.onsuccess = dfrd.resolve;
update.onerror = dfrd.reject;
}).promise());
安全地安装(可能就是这种情况),然后你可以开始查看其他代码了。
罪魁祸首似乎是解决/拒绝延期的方式。
尝试:
objectStore.put()
如果您仍有问题,那么jQuery.Deferred()
可能不会按照您的想法行事,或者只是一个错误的期望问题。
我希望它们在调用$ .when.all()时完成,并在其对应的.then()函数中执行代码,但我通过断点发现它立即执行.put()调用它,......
传递给objectStore.put(fav);
的函数是同步执行的,因此list_of_keys = []
for obj in File.objects.all().values_list('metadata', flat=True)
list_of_keys = list_of_keys + obj.keys()
确实会立即执行。目前尚不清楚您可能想要的替代行为。