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(); };
是的,这是正常的行为。 如果一个人失败了,依赖所有人的事情也会失败。 另请参阅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
回调,并且它会获得一个指示状态和结果的对象数组。