Application ($,some Array)是做什么的?

我是 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');
}
84677 次浏览

.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传递多少参数。将数组本身传递给 $.when是不可行的,因为它期望它的参数是承诺的,而不是数组。

这就是 .apply的用武之地。它接受数组,并使用每个元素作为参数调用 $.when(并确保将 this设置为 jQuery/$) ,这样它就可以工作了: -)

$.当传递给它的每个承诺都被解决/拒绝时,只有它才有可能调用回调。通常,$。当接受数量可变的参数时,使用。Application 使得传递参数数组成为可能,它非常强大。更多信息。适用范围: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

在这里,代码被完整地记录下来。

// 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');
}

$. when 接受任意数量的参数并解析 什么时候,所有这些参数都已解析。

任何功能。Application (thisValue,arrayParameter)调用函数 任何功能设置其上下文(this Value 将是该函数调用中的 这个) ,并将 arrayParameter 中的所有对象作为单独的参数传递。

例如:

$.when.apply($, [def1, def2])

与:

$.when(def1, def2)

但是 申请调用方式允许您传递一个参数数量未知的数组。(在您的代码中,您说您的 资料来自一个服务,那么这是调用 $的唯一方法)

不幸的是,我不能同意你们的观点。

$.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');
}

It this a bug? I would like to use this like the gentleman above described it.

谢谢你优雅的解决方案:

var promise;


for(var i = 0; i < data.length; i++){
promise = $.when(promise, processItem(data[i]));
}


promise.then(everythingDone);

Just one point: When using resolveWith to get some parameters, it breaks because of the initial promise set to undefined. What i did to make it work:

// 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);

也许有人会发现这个有用:

$.when.apply($, processItemsDeferred).then(everythingDone).fail(noGood);

如果有任何拒绝,不会调用 everything done