jQuery Deferred,$ .when()和fail()回调参数

当其中一个延迟操作不成功时使用$.when()时,我得到一个意外的结果。

拿这个JavaScript,创建2个延迟。 第一个成功,第二个失败。

 var f1 = function() { return $.Deferred(function(dfd) { dfd.resolve('123 from f1'); }).promise(); }; var f2 = function() { return $.Deferred(function(dfd) { dfd.reject('456 from f2'); }).promise(); }; $.when(f1(), f2()) .then(function(f1Val, f2Val) { alert('success! f1, f2: ' + JSON.stringify([f1Val, f2Val])); }) .fail(function(f1Val, f2Val) { alert('fail! f1, f2: ' + JSON.stringify([f1Val, f2Val])); }); 

自己运行: http : //jsfiddle.net/r2d3j/2/

fail! f1, f2: ["456 from f2", null] fail! f1, f2: ["456 from f2", null]

问题是在.fail()回调中,使用f2()拒绝传递的值被路由到第一个参数,其中我期望f1Value 。 这意味着我真的没有办法知道哪个延迟对象实际发布了reject() ,而且我也不知道故障数据实际属于哪个操作。

我原以为.fail()会得到参数null, '456 from f2' .fail() null, '456 from f2'因为第一个延迟没有失败。 或者我只是没有在这里做正确的延期?

如果不遵守回调中的参数顺序,我如何知道哪些延迟失败,以及哪些拒绝参数属于哪个失败延迟?

在内部,“拒绝”和“失败”路径由两个完全独立的队列处理,因此它不会按照您期望的方式工作。

为了从“when()”组中知道哪个原始Deferred失败,您可以将它们与“.reject()”调用一起传递为对象文字或其他内容的一部分。

如果任何一个参数失败, $.when()将立即执行失败的回调(传递给then()第二个参数then() 。 这是设计的。 引用文档:

http://api.jquery.com/jQuery.when/

在多个Deferreds案例中,其中一个Deferreds被拒绝,jQuery.when会立即触发其主Deferred的failCallbacks。 请注意,此时某些延迟可能仍未解决。 如果需要对此情况执行其他处理,例如取消任何未完成的ajax请求,则可以在闭包中保留对基础jqXHR对象的引用,并在failCallback中检查/取消它们。

实际上没有内置的获取回调的方法,无论其成功/失败状态如何,都会等待所有回调完成。

所以,我为你建了一个$.whenAll() 🙂
它始终等待,直到所有人都以某种方式解决:

http://jsfiddle.net/InfinitiesLoop/yQsYK/51/

 $.whenAll(a, b, c) .then( callbackUponAllResolvedOrRejected ); 

我遇到了同样的问题,我通过使用.always回调并检查我的延迟对象数组来处理它。 我有一个未知数量的ajax调用,所以我必须做以下事情:

 // array of ajax deletes var deletes = []; $checkboxes.each(function () { deletes.push(deleteFile(this)); }); $.when.apply($, deletes) .always(function () { // unfortunately .fail shortcircuits and returns the first fail, // so we have to loop the deferred objects and see what happened. $.each(deletes, function () { this.done(function () { console.log("done"); }).fail(function () { console.log("fail"); }); }); }); 

deleteFile方法返回一个promise,它有.done或.fail回调。

这允许您在所有延迟完成后采取措施。 在我的情况下,我将显示删除文件错误摘要。

我只是尝试了这个,不幸的是我不得不设置一个间隔计时器来检查它们是否都是在延迟对象的$ .each之后才真正完成的。 这看似奇怪而且违反直觉。

仍在努力了解这些延期!

http://jsfiddle.net/InfinitiesLoop/yQsYK/

如果给定多个输入,这将始终拒绝。 rejected = true; 应该被rejected |= reject;