jquery延迟 – 在第一次拒绝时调用“always”

我正在使用$.when链接一些Deferred对象,如果其中一个失败,则在失败后直接调用always方法,即使我仍然有一个处于“挂起”状态的延迟器。

 var promises = [], defs = []; for(var i=0 ; i < 10 ; i++){ defs.push($.Deferred()); promises.push(defs[i].promise()); } var res = $.when.apply($, promises); res.fail(function(){console.log('failed')}); res.done(function(){console.log('done')}); res.always(function(){console.log('always')}); res.then(function(){console.log('then, done')}, function(){console.log('then, failed')}); var j = 0; var t = setInterval(function(){ if(j < 10){ if(j < 5) { console.log('resolve'); defs[j++].resolve(); } else { console.log('reject'); defs[j++].reject(); } } else { clearInterval(t); } }, 200); 

检查这个jsfiddle 。

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

它是按设计:一旦所有Deferreds解决,该方法将解析其主延期,或者一旦Deferreds被拒绝,该方法将拒绝主延期。 […]请注意,此时某些延期可能仍未得到解决

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

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

像这样的东西:

 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(); }; 

http://jsfiddle.net/cSy2K/2/

是的,这是正常的行为。 如果一个人失败了,依赖所有人的事情也会失败。 另请参阅jQuery文档 。

因此,您要么必须手动跟踪它们,要么只将已解决的Promise提供到以下when

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

有了这个,你的res只会在处理完所有的promises时调用done回调,并且它会获得一个指示状态和结果的对象数组。