【问题标题】:How to handle fail of $.when promise?如何处理 $.when 承诺的失败?
【发布时间】:2014-02-23 04:02:56
【问题描述】:

我不明白 $.when 在传递多个 AJAX 调用时在失败期间的工作原理。如果失败,是否会触发失败回调?另外,失败的参数是什么,每个ajax一个还是一个失败共享?

$.when(
    $.ajax('/url1'),
    $.ajax('/url2'))
   .done(function (resp1, resp2) {

    }).fail(function (??) {

    });

【问题讨论】:

  • 如果一个 deferred 失败了,包装 $.when 也会立即失败。
  • 有道理,但是在失败中,我怎么知道哪一个失败了?每个 AJAX 调用是否有一个失败参数或隐藏在单个失败参数中?
  • 如果一个失败,包装$.when的失败会立即被调用,所以参数将是第一个$.ajax失败,因为那是外部fail()将被调用的时候,有道理吗?
  • 正如 Adeano 所说的第一次失败。如果您想了解所有失败,而不仅仅是第一个失败,请为每个 $.ajax() 承诺单独设置 .fail() 处理程序。

标签: javascript jquery ajax promise deferred


【解决方案1】:

我正在处理类似的事情,并认为它可能对某人有所帮助。

A CodePen playground with $.when

 var d1 = $.Deferred().fail(function(a){ console.log('on fail 1', a) }), 
    d2 = $.Deferred().fail(function(a){ console.log('on fail 2', a) }),
    d3 = $.Deferred().fail(function(a){ console.log('on fail 3', a) });
$.when(d1, d2, d3)
.then(function (a, b, c){
  console.log('then: ', a, b, c);
})
.fail(function (a, b, c) { 
  // only reports the first one that failed
  console.log('fail: ', a, b, c); 
})
.always(function(a, b, c){
  console.log('always: ', a, b, c);
});
d1.resolve("d1!");
d2.reject("d2!");
d3.reject("d3!");

A way to 'recover' from 1 failed in the array of deferreds

'use strict';
var getConfigRequestDef = $.Deferred();
var getConfigDef = $.Deferred();
var getStatusRequestDef = $.Deferred();
var getStatusDef = $.Deferred();
getConfigRequestDef.then(function (cfg) {
    return getConfigDef.resolve(cfg);
}, function (c) {
    c.hasError = true;
    getConfigDef.resolve(c);
});
getStatusRequestDef.then(function (status) {
    return getStatusDef.resolve(status);
}, function (s) {
    s.hasError = true;
    getStatusDef.resolve(s);
});
var results = $.when(getConfigDef, getStatusDef).then(function (config, status) {
    console.log('The when\'s then: ', JSON.stringify(config), JSON.stringify(status));
});
var cfg = {
    id: 10,
    type: 'config',
    hasError: false
};
var statusObj = {
    id: 30,
    type: 'status',
    hasError: false
};
getConfigRequestDef.reject(cfg);
getStatusRequestDef.reject(statusObj);

【讨论】:

    【解决方案2】:

    .then() 实际上最多需要三个参数(成功、失败、进度)。您可以使用.fail(),如其他答案中所述,也可以执行以下操作:

    $.when(async).then(function success(resp) {
            console.log('success');
        }, function fail(resp) {
            console.log('fail');
        });
    

    【讨论】:

      【解决方案3】:

      当任何承诺被拒绝时,最终的失败将被调用。 如果你想为每个人做一些不同的事情,你可以尝试这样的事情:

      $.when(
          $.ajax('/url1').fail(function () { console.dir('fail 1'); }),
          $.ajax('/url2').fail(function () { console.dir('fail 2'); }))
      .done(function (resp1, resp2) {
      
      }).fail(function () {
          console.dir('fail any');
      });
      

      Fail any 将在其中一个 ajax 请求失败后立即调用,因此之后可能会调用其他特定于请求的失败。

      【讨论】:

        【解决方案4】:

        这应该很容易检查吧?

        var d1 = $.Deferred(), d2 = $.Deferred();
        
        $.when(d1, d2)
           .fail(function (a, b) { 
              console.log(a, b); 
           });
        
        d2.reject("hi!");
        

        输出为hi! undefined。所以只有一个参数被传递。

        http://jsfiddle.net/22b3L/

        【讨论】:

        • 你真的不必测试它,很明显,如果$.when 的外部fail()$.when 中的一个延迟被拒绝时立即调用,即ajax 失败,参数将仅从失败的 ajax 调用传递,因为不能保证其他 ajax 调用将完成,并且外部 fail() 会立即调用,因此无法传递其他任何内容。
        • when(d1,d2).done(function (a, b) {}) 确实有两个参数。解决此问题的一种方法是要求:when_array([d1, d2]).done(spread(function (a, b) {}))。根据我使用 jQuery 的经验,它们有一些非常好的,但稍微随意的语法糖。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-06
        • 2012-06-28
        • 2013-11-10
        • 1970-01-01
        相关资源
        最近更新 更多