Javascript $.when.apply($, someArray) 有什么作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14777031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does $.when.apply($, someArray) do?
提问by manafire
I'm reading about Deferreds and Promisesand keep coming across $.when.apply($, someArray). I'm a little unclear on what this does exactly, looking for an explanation that one lineworks exactly (not the entire code snippet). Here's some context:
我正在阅读有关 Deferreds 和 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');
}
回答by Rocket Hazmat
.applyis used to call a function with an array of arguments. It takes each element in the array, and uses each as a parameter to the function. .applycan also change the context (this) inside a function.
.apply用于调用带有参数数组的函数。它获取数组中的每个元素,并将每个元素用作函数的参数。 .apply还可以更改this函数内的上下文 ( )。
So, let's take $.when. It's used to say "when all these promises are resolved... do something". It takes an infinite (variable) number of parameters.
所以,让我们拿$.when. 它习惯于说“当所有这些承诺都得到解决时……做点什么”。它需要无限(可变)数量的参数。
In your case, you have an array of promises; you don't know how many parameters you're passing to $.when. Passing the array itself to $.whenwouldn't work, because it expects its parameters to be promises, not an array.
就您而言,您有一系列承诺;你不知道你传递了多少参数$.when。将数组本身传递给它是$.when行不通的,因为它希望它的参数是 promise,而不是数组。
That's where .applycomes in. It takes the array, and calls $.whenwith each element as a parameter (and makes sure the thisis set to jQuery/$), so then it all works :-)
这就是.apply进来的地方。它接受数组,并$.when以每个元素作为参数进行调用(并确保将this其设置为jQuery/ $),然后一切正常:-)
回答by Pablo
$.whentakes any number of parameters and resolves whenall of these have resolved.
$.when接受任意数量的参数,并在所有这些都解析后解析。
anyFunction.apply(thisValue, arrayParameters) calls the function anyFunctionsetting its context (thisValue will be the thiswithin that function call) and passes all the objects in arrayParameters as individual parameters.
anyFunction.apply(thisValue, arrayParameters) 调用函数anyFunction设置其上下文(thisValue 将是该函数调用中的this)并将 arrayParameters 中的所有对象作为单独的参数传递。
For example:
例如:
$.when.apply($, [def1, def2])
Is the same as:
是相同的:
$.when(def1, def2)
But the applyway of calling allows you to pass an array of unknown number of parameters. (In your code, you are saying that you datacomes from a service, then that is the only way to call $.when)
但是apply调用方式允许您传递未知数量的参数数组。(在您的代码中,您是说您的数据来自服务,那么这是调用$.when的唯一方法)
回答by Yanick Rochon
Here, the code fully documented.
在这里,代码完全记录。
// 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');
}
回答by user3388213
Unfortunately I can not agree with you guys.
不幸的是,我不能同意你们的看法。
$.when.apply($, processItemsDeferred).always(everythingDone);
Will call everythingDoneas soon as one deferred gets rejected, even if there are other deferreds that are pending.
将everythingDone在一个 deferred 被拒绝后立即调用,即使还有其他 deferred待处理。
Heres the full script (I recommend http://jsfiddle.net/):
这是完整的脚本(我推荐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');
}
It this a bug? I would like to use this like the gentleman above described it.
这是一个错误吗?我想像上面那位先生描述的那样使用它。
回答by Vlado Kurelec
Maybe someone can find this useful:
也许有人会发现这很有用:
$.when.apply($, processItemsDeferred).then(everythingDone).fail(noGood);
everythingDone isn't called in case of any reject
如果有任何拒绝,则不会调用everythingDone
回答by user3544352
Thanks for your elegant solution:
感谢您的优雅解决方案:
var promise;
for(var i = 0; i < data.length; i++){
promise = $.when(promise, processItem(data[i]));
}
promise.then(everythingDone);
Just one point: When using resolveWithto get some parameters, it breaks because of the initial promise set to undefined. What i did to make it work:
只有一点:当resolveWith用于获取一些参数时,它会因为初始承诺设置为未定义而中断。我做了什么使它工作:
// 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);
回答by Roger C
$.when alone makes it possible for a callback to be called when every promises passed to it are resolved/rejected. Normally, $.when takes a variable number of arguments, using .apply makes it possible to pass it an array of arguments, it's very powerful. For more info on .apply: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply
$.when 单独使得在传递给它的每个承诺都被解决/拒绝时调用回调成为可能。通常, $.when 接受可变数量的参数,使用 .apply 可以将参数数组传递给它,它非常强大。有关 .apply 的更多信息:https: //developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

