jquery deferred—第一次拒绝时调用“always”

时间:2022-12-18 19:42:51

I'm using $.when to chain some Deferred objects, and if one of them fail, the always method will be called directly after the failure, even if I still have some deferrer in a "pending" state.

我用美元。当链接一些被延迟的对象时,如果其中一个失败了,那么always方法将在失败后被直接调用,即使我仍然有一些处于“pending”状态的延迟。

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

Check this jsfiddle.

检查这个jsfiddle。

Maybe it's the normal behavior. But, in this case, how can I catch the end of my chain even if some of them have failed?

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

2 个解决方案

#1


11  

It's by design: The method will resolve its master Deferred as soon as all the Deferreds resolve, or reject the master Deferred as soon as one of the Deferreds is rejected. [...] Note that some of the Deferreds may still be unresolved at that point.

它是通过设计实现的:方法将在所有延迟解决时立即解析它的主进程,或者在其中一个延迟解决时立即拒绝主进程。[…请注意,在这一点上,一些延期可能仍未解决。

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

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

You can save references to all deferreds and track them separately.

您可以保存对所有延迟的引用,并分别跟踪它们。

Something like this:

是这样的:

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/

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

#2


1  

Yes, it is normal behavior. If one fails, the thing that relies on all fails as well. See also the jQuery docs.

是的,这是正常的行为。如果一个人失败了,依赖于一切的东西也会失败。参见jQuery文档。

So, you either have to track them manually, or you feed only resolved Promises into when:

因此,您要么必须手动跟踪它们,要么只将解析后的承诺输入到when:

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

With this, your res will only call the done callback when all promises are processed, and it will get an array of objects indicating status and result of them.

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

#1


11  

It's by design: The method will resolve its master Deferred as soon as all the Deferreds resolve, or reject the master Deferred as soon as one of the Deferreds is rejected. [...] Note that some of the Deferreds may still be unresolved at that point.

它是通过设计实现的:方法将在所有延迟解决时立即解析它的主进程,或者在其中一个延迟解决时立即拒绝主进程。[…请注意,在这一点上,一些延期可能仍未解决。

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

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

You can save references to all deferreds and track them separately.

您可以保存对所有延迟的引用,并分别跟踪它们。

Something like this:

是这样的:

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/

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

#2


1  

Yes, it is normal behavior. If one fails, the thing that relies on all fails as well. See also the jQuery docs.

是的,这是正常的行为。如果一个人失败了,依赖于一切的东西也会失败。参见jQuery文档。

So, you either have to track them manually, or you feed only resolved Promises into when:

因此,您要么必须手动跟踪它们,要么只将解析后的承诺输入到when:

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

With this, your res will only call the done callback when all promises are processed, and it will get an array of objects indicating status and result of them.

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