等待多个延迟对象完成并使用已解析的值

时间:2016-01-21 08:29:31

标签: jquery

我试图想办法等待多个延迟对象并在完成后处理它们,可能就像为延迟对象启动下一组。

我被困了,因为下面的结果不是预期的结果。 我期待结果为

allDone resovled values are 1,2,3

实际结果是

allDone resovled values are 1,2
var dfd1 = new $.Deferred();
var dfd2 = new $.Deferred();
var dfd3 = new $.Deferred(); 
var dfds = [ dfd1, dfd2, dfd3 ]; 
var resolvedValues = [];

$.when.apply($, dfds).done(function() {     
    dfds.forEach(function(dfd){
        console.log("inloop");      
        dfd.promise().done(function(value) {
            resolvedValues.push(value);         
        });     
    });
    console.log("allDone resovled values are" + resolvedValues);
})

dfd1.resolve(1);
dfd2.resolve(2);
dfd3.resolve(3);

1 个答案:

答案 0 :(得分:10)

对于 why ,请参阅下文。但是你过度复杂了。 :-)你给出从when得到的最终承诺的回调给你解决的值作为参数:

$.when.apply($, dfds).done(function(a, b, c) {
  // Here, a is 1, b is 2, c is 3
  // Or you can access them on `arguments`
})

直播示例:



var dfd1 = new $.Deferred();
var dfd2 = new $.Deferred();
var dfd3 = new $.Deferred(); 
var dfds = [ dfd1, dfd2, dfd3 ]; 
var resolvedValues = [];

$.when.apply($, dfds).done(function() {
  // Use a trick to turn `arguments` into a real array
  var a = Array.prototype.slice.call(arguments);
  // Show what we got
  snippet.log("allDone: " + a.join(", "));
})

dfd1.resolve(1);
dfd2.resolve(2);
dfd3.resolve(3);

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
&#13;
&#13;

旁注:我假设您故意处理数组。如果你需要等待固定数量的承诺,只需使用更简单的表格

$.when(dfd1, dfd2, dfd3).then(function(a, b, c) {
    // ...
});

这里为什么你得到了你得到的非常奇怪的结果:jQuery&#39 Deferred / Promise个对象有一个问题是他们混乱:当你打电话给done时,你不知道你的回调是否会同时执行或< EM>异步。这是一个严重的缺陷,而且真正的Promises / A +实现没有(回调总是异步的)。

如果承诺尚未解决,jQuery将异步调用回调 。但如果未解决,它会将其称为同步

var d1 = $.Deferred();
d1.done(function() {
    console.log("I'm called asynchronously");
});
d1.resolve();

var d2 = $.Deferred();
d2.resolve();
d2.done(function() {
    console.log("I'm called synchronously");
});

因此,您的代码中发生的事情是done触发的整个when回调在最后一次done回调期间被解雇承诺得到解决(dfd3)。由于承诺未被标记为已解决,直到 完成done回调后,当您的代码运行时,dfd1dfd2已解决但{ {1}}仍处于解决之中。因此,dfd3dfd1同步调用内部回调,但dfd2异步调用 。因此,在将dfd3返回值推送到阵列之前,您需要输出结果。