10

$.whenいくつかのDeferredオブジェクトをチェーンするために使用していますが、そのうちの1つが失敗するalwaysと、「保留中」の状態のdeferrerがまだある場合でも、失敗の直後にメソッドが呼び出されます。

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を確認してください。

多分それは正常な振る舞いです。しかし、この場合、一部が失敗した場合でも、どうすればチェーンの終わりをキャッチできますか?

4

2 に答える 2

11

これは仕様によるものです。メソッドは、すべての Deferred が解決されるとすぐにそのマスター Deferred を解決するか、 Deferred の1 つが拒否されるとすぐにマスター Deferred を拒否します。[...] Deferred の一部は、その時点でまだ解決されていない可能性があることに注意してください。

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

すべての deferred への参照を保存し、それらを個別に追跡できます。

このようなもの:

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/

于 2012-11-21T12:41:16.453 に答える
1

はい、正常な動作です。1 つが失敗すると、すべてに依存するものも失敗します。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});
  })
);

これにより、すべての promise が処理されたときresにのみコールバックが呼び出さdoneれ、それらのステータスと結果を示すオブジェクトの配列が取得されます。

于 2012-11-21T14:12:15.557 に答える