For the 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
console.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>
旁注:我假设您正在故意处理数组。如果您有固定数量的承诺需要等待,只需使用更简单的形式
$.when(dfd1, dfd2, dfd3).then(function(a, b, c) {
// ...
});
Here's why你得到了非常奇怪的结果:jQuery'sDeferred
/Promise
对象有一个问题,因为它们是chaotic: 你打电话时done
在他们身上,你不知道你的回调是否会被执行同步地 or 异步地。这是一个严重的缺陷,也是真正的 Promises/A+ 实现所不具备的缺陷(回调始终是异步的)。
jQuery 将调用回调异步地如果承诺尚未兑现。但它会调用它同步地 if it isn't解决:
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
火被点燃during the done
最后一个已解决的承诺的回调(dfd3
)。由于承诺没有标记为已解决,直到after the done
回调已经完成,当你的代码运行时,dfd1
and dfd2
已解决但是dfd3
目前仍在解决过程中。所以你的内部回调被同步调用dfd1
and dfd2
but 异步地 for dfd3
。所以你在之前输出你的结果dfd3
返回值已被推送到您的数组中。