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

Ale*_*yne 23 javascript jquery jquery-deferred

$.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]));
    });
Run Code Online (Sandbox Code Playgroud)

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

我明白了 fail! f1, f2: ["456 from f2", null]

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

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

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

Inf*_*oop 25

$.when()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 );
Run Code Online (Sandbox Code Playgroud)

  • 不,它不会触发当时的回调..它会触发失败的回调.(在技术上可以是传递给'then'的'第二'回调,但无论如何它与'then'回调不一样,大多数人在阅读你的答案时会假设是'成功'回调). (3认同)
  • @hippietrail这两者都是.then()在延迟被"解决"或"被拒绝"时触发.这归类为拒绝,因此它会触发. (2认同)

Poi*_*nty 5

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

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