什么是将JQuery Promise数组转换为数组JQuery承诺的最简洁方法?

我遇到了一个arrays中有多个JQuery Promises的情况

var arrayOfPromises = [ $.Deferred(), $.Deferred(), $.Deferred(), $.Deferred() ] 

并需要将其转换为数组的JQuery承诺

 var promiseOfArray = someTransform(arrayOfPromises) 

哪里

 promiseOfArray.done(function(anArray){ alert(anArray.join(",")); }); 

使用文本创建警报

RESULT1,结果2,result3,result4

我目前在coffeescript中定义someTransform为

 someTransform = (arrayOfPromises) -> $.when(arrayOfPromises...).pipe (promises...) -> promises 

转换为以下javascript

 var someTransform, __slice = [].slice; someTransform = function(arrayOfPromises) { return $.when.apply($, arrayOfPromises).pipe(function() { var promises; promises = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return promises; }); }; 

这是我正在寻找的结果的jsFiddle 。

我想知道是否有更好(更短,更清洁)的方法来定义someTransform来实现相同的结果?

您可以将数组作为参数应用于$.when

 var promiseOfArray = $.when.apply($, arrayOfPromises); 

为了更清楚地使用这个,我喜欢在$添加一个方法:

 $.whenall = function(arr) { return $.when.apply($, arr); }; 

现在你可以这样做:

 $.whenall([deferred1, deferred2, ...]).done(...); 

更新:默认情况下, done处理程序将每个结果作为单独的参数传递; 你没有得到一系列的结果。

由于您需要处理任意数量的Deferred,您可以使用特殊的隐式arguments对象来循环结果。

 $.whenall([d1, d2, ...]).done(function() { for (var i = 0; i < arguments.length; i++) { // do something with arguments[i] } }); 

如果你真的只想加入所有Deferred的字符串结果,我们可以使用一个小数组hackery。 arguments类似于数组,但不是Array

 $.whenall([d1, d2, ...]).done(function() { alert(Array.prototype.join.call(arguments, ',')); }); 

如果你想将一系列结果返回给你的done回调,我们可以调整whenall 来做到这一点 :

 $.whenall = function(arr) { return $.when.apply($, arr).pipe(function() { return Array.prototype.slice.call(arguments); }); }; 

当我们需要在多个promises上调用它时,它总是打扰我总是键入“丑陋”行$.when.apply 。 但是Function.prototype.bind用于救援!

 var when = Function.prototype.apply.bind( jQuery.when, null ); 

现在,我们可以打电话

 when( someArrayWithPromises ).done(function() { }); 

Function.prototype.bind是ES5的一部分,可以跨浏览器广泛使用。 如果您需要支持非常古老的浏览器,还有大量的简易垫片可用