Javascript jquery deferred-“延迟”;“始终”;在第一次拒绝时被要求

Javascript jquery deferred-“延迟”;“始终”;在第一次拒绝时被要求,javascript,jquery,jquery-deferred,Javascript,Jquery,Jquery Deferred,我正在使用$。当链接一些延迟对象时,如果其中一个失败,则在失败后将直接调用始终方法,即使我仍有一些延迟器处于“挂起”状态 var-promissions=[],defs=[]; 对于(变量i=0;i

我正在使用
$。当
链接一些延迟对象时,如果其中一个失败,则在失败后将直接调用
始终
方法,即使我仍有一些延迟器处于“挂起”状态

var-promissions=[],defs=[];
对于(变量i=0;i<10;i++){
defs.push($.Deferred());
promises.push(defs[i].promise());
}
var res=$.when.apply($,承诺);
res.fail(函数(){console.log('failed')});
res.done(函数(){console.log('done')});
res.always(函数(){console.log('always')});
res.then(function(){console.log('then,done')},
函数(){console.log('then,failed')});
var j=0;
var t=setInterval(函数(){
如果(j<10){
if(j<5){
console.log('resolve');
defs[j++].resolve();
}
否则{
console.log(“拒绝”);
defs[j++].reject();
}
}
否则{
净间隔(t);
}
}, 200); 
检查


也许这是正常的行为。但是,在这种情况下,即使其中一些失败了,我怎么能抓住我的链条的末端呢?

这是出于设计:该方法将在所有延迟解决后立即解决其主延迟,或者在一个延迟被拒绝后立即拒绝主延迟。 [...] 请注意,此时,一些延迟可能仍然未解决

您可以保存对所有延迟的引用并单独跟踪它们

大概是这样的:

var whenAll = function() {
   var dfd = $.Deferred(),
       len = arguments.length,
       counter = 0,
       state = "resolved",
       resolveOrReject = function() {
           if(this.state() === "rejected"){
               state = "rejected";
           }
           counter++;

           if(counter === len) {
               dfd[state === "rejected"? "reject": "resolve"]();   
           }

       };


    $.each(arguments, function(idx, item) {
        item.always(resolveOrReject); 
    });

   return dfd.promise();    
};

是的,这是正常的行为。如果一个人失败了,那么依赖一切的东西也会失败。另见

因此,您要么必须手动跟踪它们,要么在时只将已解决的承诺输入到

promises.push( defs[i].promise().then(function(x) {
      return {result:x,resolved:true};
  }, function(x) {
      return (new $.Deferred).resolve({result:x,resolved:false});
  })
);

这样,您的
res
将仅在处理所有承诺时调用
done
回调,它将获得一个对象数组,指示它们的状态和结果。

谢谢@yury tarabanko!我喜欢扩展jQuery并添加可重用方法来查看所有延迟端的想法,即使它们失败了。基于您的想法和“when”jQuery源代码,我再次执行了“whenAll”,如果您有时间,请检查源代码;)
promises.push( defs[i].promise().then(function(x) {
      return {result:x,resolved:true};
  }, function(x) {
      return (new $.Deferred).resolve({result:x,resolved:false});
  })
);