我reading about Deferreds and Promises并不断遇到$.when.apply($, someArray)
。我有点不清楚它到底是做什么的,寻找一行完全正常工作的解释(不是整个代码片段)。以下是一些背景信息:
var data = [1,2,3,4]; // the ids coming back from serviceA
var processItemsDeferred = [];
for(var i = 0; i < data.length; i++){
processItemsDeferred.push(processItem(data[i]));
}
$.when.apply($, processItemsDeferred).then(everythingDone);
function processItem(data) {
var dfd = $.Deferred();
console.log('called processItem');
//in the real world, this would probably make an AJAX call.
setTimeout(function() { dfd.resolve() }, 2000);
return dfd.promise();
}
function everythingDone(){
console.log('processed all items');
}
答案 0 :(得分:152)
.apply
用于调用带有参数数组的函数。它接受数组中的每个元素,并将每个元素用作函数的参数。 .apply
也可以更改函数内的上下文(this
)。
所以,我们来看$.when
。它习惯于说“当所有这些承诺得到解决时......做点什么”。它需要无限(可变)数量的参数。
在你的情况下,你有一系列的承诺;你不知道你传递给$.when
的参数有多少。将数组本身传递给$.when
是行不通的,因为它希望它的参数是promises,而不是数组。
这就是.apply
的用武之地。它接受数组,并以每个元素作为参数调用$.when
(并确保this
设置为jQuery
/ $
),那么一切正常: - )
答案 1 :(得分:61)
$.when接受任意数量的参数,并在所有这些参数解析后解析。
anyFunction .apply(thisValue,arrayParameters)调用函数 anyFunction 设置其上下文(thisValue将是该函数调用中的 this )并将arrayParameters中的所有对象作为单独的参数传递。
例如:
$.when.apply($, [def1, def2])
与:
相同$.when(def1, def2)
但是 apply 调用方式允许您传递一个包含未知数量参数的数组。 (在您的代码中,您说的是数据来自服务,那么这是调用 $。的唯一方式。时)
答案 2 :(得分:13)
这里,代码完整记录。
// 1. Declare an array of 4 elements
var data = [1,2,3,4]; // the ids coming back from serviceA
// 2. Declare an array of Deferred objects
var processItemsDeferred = [];
// 3. For each element of data, create a Deferred push push it to the array
for(var i = 0; i < data.length; i++){
processItemsDeferred.push(processItem(data[i]));
}
// 4. WHEN ALL Deferred objects in the array are resolved THEN call the function
// Note : same as $.when(processItemsDeferred[0], processItemsDeferred[1], ...).then(everythingDone);
$.when.apply($, processItemsDeferred).then(everythingDone);
// 3.1. Function called by the loop to create a Deferred object (data is numeric)
function processItem(data) {
// 3.1.1. Create the Deferred object and output some debug
var dfd = $.Deferred();
console.log('called processItem');
// 3.1.2. After some timeout, resolve the current Deferred
//in the real world, this would probably make an AJAX call.
setTimeout(function() { dfd.resolve() }, 2000);
// 3.1.3. Return that Deferred (to be inserted into the array)
return dfd.promise();
}
// 4.1. Function called when all deferred are resolved
function everythingDone(){
// 4.1.1. Do some debug trace
console.log('processed all items');
}
答案 3 :(得分:1)
不幸的是我不同意你们的意见。
$.when.apply($, processItemsDeferred).always(everythingDone);
只要延迟获得被拒绝,就会立即致电everythingDone
,即使还有其他延迟待审。
继承完整的脚本(我推荐http://jsfiddle.net/):
var data = [1,2,3,4]; // the ids coming back from serviceA
var processItemsDeferred = [];
for(var i = 0; i < data.length; i++){
processItemsDeferred.push(processItem(data[i]));
}
processItemsDeferred.push($.Deferred().reject());
//processItemsDeferred.push($.Deferred().resolve());
$.when.apply($, processItemsDeferred).always(everythingDone);
function processItem(data) {
var dfd = $.Deferred();
console.log('called processItem');
//in the real world, this would probably make an AJAX call.
setTimeout(function() { dfd.resolve(); }, 2000);
return dfd.promise();
}
function everythingDone(){
alert('processed all items');
}
这是一个错误吗?我想像上面描述的绅士一样使用它。
答案 4 :(得分:1)
也许有人会发现这个有用:
$.when.apply($, processItemsDeferred).then(everythingDone).fail(noGood);
在任何拒绝情况下都不会调用EverythingDone
答案 5 :(得分:0)
$。单独使得当传递给它的每个promise都被解析/拒绝时,可以调用回调。通常,$ .when采用可变数量的参数,使用.apply可以传递一个参数数组,它非常强大。有关.apply:https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply
的更多信息答案 6 :(得分:0)
感谢您的优雅解决方案:
var promise;
for(var i = 0; i < data.length; i++){
promise = $.when(promise, processItem(data[i]));
}
promise.then(everythingDone);
只有一点:当使用resolveWith
获取某些参数时,由于初始承诺设置为undefined,它会中断。我做了什么让它发挥作用:
// Start with an empty resolved promise - undefined does the same thing!
var promise;
for(var i = 0; i < data.length; i++){
if(i==0) promise = processItem(data[i]);
else promise = $.when(promise, processItem(data[i]));
}
promise.then(everythingDone);