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

我正在阅读关于延期和承诺,并继续来$.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'); } 

.apply被用来用一个参数数组来调用一个函数。 它采用数组中的每个元素,并将每个元素用作函数的参数。 .apply也可以改变函数内的上下文( this )。

那么,让我们拿$.when 。 这是用来说“当所有这些承诺解决…做一些事情”。 它需要一个无限的(可变)数量的参数。

就你而言,你有一系列的承诺; 你不知道有多lessparameter passing给$.when 。 将数组本身传递给$.when将不起作用,因为它期望它的参数是promise,而不是数组。

这就是.apply进来的地方。它需要数组,并且以每个元素作为参数调用$.when (并确保将this设置为jQuery / $ ),这样就可以工作:-)

$ .when获取任何数量的参数,并解决所有这些都解决时。

anyFunction .apply(thisValue,arrayParameters)调用函数anyFunction设置其上下文(thisValue将是这个 )和arrayParameters中的所有参数。

例如:

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

是相同的:

 $.when(def1, def2) 

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

在这里,代码完整logging。

 // 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.apply($, processItemsDeferred).always(everythingDone); 

一旦一个延期被拒绝 ,即使还有其他待决的延期,也会立即调用everythingDone

下面是完整的脚本(我build议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'); } 

这是一个错误? 我想用这个像上面描述的那位先生一样。

只有当每个承诺传递给它时,才能调用callback函数。 通常,$ .when需要可变数量的参数时,使用.apply可以将它传递给一个参数数组,它非常强大。 有关.apply的更多信息: https : //developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

感谢您的优雅解决scheme:

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

只要一点:当使用resolveWith获取一些参数时,由于最初的promise被设置为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);