【问题标题】:How run a function only after all deferred are resolved by using jQuery?仅在使用 jQuery 解决所有延迟后如何运行函数?
【发布时间】:2017-06-11 22:43:48
【问题描述】:

我不明白问题出在哪里,我在这里阅读了几个问题,但没有类似的东西。 我不能使用函数来返回承诺,我只需将所有承诺放在一个数组中并将其传递给“$.when”函数。

var pr = [];
var count = 3; 
while(count--){
   setTimeout(function(){ 
     var def = $.Deferred();
     pr.push(def.promise());    
     console.log('COUNT: '+count); def.resolve(count); 
   }, Math.random()*2000);
}  

$.when.apply($, pr).done(function(d){
     console.log("LOG:",d);
});

显然不起作用,因为 WHEN pr 到那时是空的。 怎么解决?

【问题讨论】:

  • 您需要立即创建延迟(以便您可以将它们传递给$.when),而不是将来的某个时候!

标签: jquery promise jquery-deferred .when


【解决方案1】:

您只是在它们运行后将延迟添加到数组中。关键是您希望它们在数组中预先放置,然后当它们全部 resolve 执行某些功能时。

var defA = $.Deferred();
var pr = [defA.promise()];
var count = 3; 

var defB = $.Deferred();
pr.push(defB.promise());     
    
var defC = $.Deferred();
pr.push(defC.promise());     
    

setTimeout(function(){ 
    console.log('COUNT: '+count--); defB.resolve(count); 

}, Math.random()*2000);

setTimeout(function(){ 
    console.log('COUNT: '+count--); defC.resolve(count); 
    defA.resolve(11011);
}, Math.random()*2000);


$.when.apply($, pr).done(function(d){
     console.log("LOG:",d);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

对于您的更新,您还需要使用闭包,因为 count 将在异步工作完成时发生变化(即,如果没有它,您将被记录 count: 0 三次)。此闭包还具有将def 保持在每次迭代的本地范围内的简洁副作用。此问答中的更多信息: JavaScript closure inside loops – simple practical example

var pr = [];
var count = 3; 
while(count--){
   
   (function(x){
       var def = $.Deferred();
       pr.push(def.promise());    
       setTimeout(function(){        
        
          console.log('COUNT: '+ x); 
          def.resolve(x); 
       }, Math.random()*2000);
     
   })(count);
}  

$.when.apply($, pr).done(function(){
     console.log("LOG:",arguments);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

编辑 - 将回调更改为 when 以便您可以看到,即使它们以随机顺序解析,您也会按照它们进入的顺序返回结果。(即 aruments[0] 将始终为 @987654331 @即使那个可能没有先解决)

【讨论】:

  • 如果我在一段时间/for/each 中创建 $.Deferred,我该怎么做?
  • @Donovant 提出正确的问题是一个好的开始。如果您的问题真的是b,请不要问a。但是,无论它们是在一条线上还是在一个循环中,都不应该有所作为。在它正在执行的异步工作之外创建 deferrd。
  • @Donovant 我猜你不打算count-- 两次?
  • @Donovant 答案已更新。循环稍微复杂一点,但只是。
猜你喜欢
  • 2015-06-23
  • 2011-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多