Javascript $.when.apply($,someArray)做什么?

Javascript $.when.apply($,someArray)做什么?,javascript,jquery,asynchronous,promise,Javascript,Jquery,Asynchronous,Promise,我正在和不断遇到$.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(pr

我正在和不断遇到
$.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');
}
var数据=[1,2,3,4];//从serviceA返回的ID
var processItemsFerred=[];
对于(变量i=0;i
用于调用具有参数数组的函数。它接受数组中的每个元素,并将每个元素用作函数的参数
.apply
还可以更改函数内部的上下文(

那么,让我们以
$为例。这句话的意思是“当所有这些承诺都解决了……做点什么”。它需要无限(可变)数量的参数

在你的情况下,你有一系列的承诺;您不知道要传递给
$的参数有多少。将数组本身传递给
$。当
不起作用时,因为它希望其参数是承诺,而不是数组


这就是
.apply
的作用所在。它接受数组并调用
$。当
将每个元素作为参数时(并确保
this
设置为
jQuery
/
$
),这样它就可以全部工作:-)

$。当传递给它的每个承诺都被解析/拒绝时,单独调用回调是可能的。通常,$.when接受可变数量的参数时,使用.apply可以向其传递一个参数数组,它非常强大。有关.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');
}
//1。声明一个包含4个元素的数组
var数据=[1,2,3,4];//从serviceA返回的ID
// 2. 声明延迟对象的数组
var processItemsFerred=[];
// 3. 对于每个数据元素,创建一个延迟推送到数组
对于(变量i=0;i
接受任意数量的参数,并在所有这些参数都已解析时解析

anyFunction.apply(thisValue,arrayParameters)调用函数anyFunction设置其上下文(thisValue将是该函数调用中的this),并将arrayParameters中的所有对象作为单个参数传递

例如:

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

$.when(def1, def2)

但是apply调用方式允许您传递未知数量的参数数组。(在你的代码中,你说你的数据来自服务,那么这是调用$.when的唯一方法)

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

$.when.apply($, processItemsDeferred).always(everythingDone);
当一个延迟被拒绝时,将调用
所有已完成的事情
,即使还有其他延迟被挂起

以下是完整的脚本(我推荐):

var数据=[1,2,3,4];//从serviceA返回的ID
var processItemsFerred=[];
对于(变量i=0;i

这是虫子吗?我想像上面那位先生所描述的那样使用它。

感谢您优雅的解决方案:

var promise;

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

promise.then(everythingDone);

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

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

任何拒绝都不会调用everythingDone。when.apply($,array)
与when(array)
不同。这与:
$相同。当(数组[0]、数组[1]、…)
这是与一起使用的主要原因。apply,您不知道ProcessItemsFerred有多少元素
。done()
可以用来代替
。那么在这种情况下,请参考,有一个要下划线的延迟端口,允许将单个数组传递给
时,您不需要使用
apply
了解有关
的更多信息。apply
:.related:OP在第一句中引用的文章已移动了位置-现在位于:。当多个承诺传递给$.when方法时。他们将按什么顺序执行?一个接一个还是并行?@Darshan:你不会“跑”承诺。你要等待他们被解决。它们是在创建时执行的,
$。当
只是等待它们全部完成,然后再继续。那么差额呢
// 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);