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

sol*_*oth 15 javascript jquery promise coffeescript

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

var arrayOfPromises = [ $.Deferred(), $.Deferred(), $.Deferred(), $.Deferred() ]
Run Code Online (Sandbox Code Playgroud)

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

var promiseOfArray = someTransform(arrayOfPromises)
Run Code Online (Sandbox Code Playgroud)

哪里

promiseOfArray.done(function(anArray){
  alert(anArray.join(","));
});
Run Code Online (Sandbox Code Playgroud)

使用文本创建警报

RESULT1,结果2,result3,result4

我目前someTransform在coffeescript中定义为

someTransform = (arrayOfPromises) ->
  $.when(arrayOfPromises...).pipe (promises...) ->
    promises
Run Code Online (Sandbox Code Playgroud)

它转换为以下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;
  });
};
Run Code Online (Sandbox Code Playgroud)

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

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

jos*_*736 34

您只需数组作为参数应用即可$.when.

var promiseOfArray = $.when.apply($, arrayOfPromises);
Run Code Online (Sandbox Code Playgroud)

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

$.whenall = function(arr) { return $.when.apply($, arr); };
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

$.whenall([deferred1, deferred2, ...]).done(...);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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

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


jAn*_*ndy 6

$.when.apply当我们需要在多个承诺上调用它时,它总是困扰我总是键入"丑陋"的行.但是Function.prototype.bind为了救援!

var when = Function.prototype.apply.bind( jQuery.when, null );
Run Code Online (Sandbox Code Playgroud)

现在,我们可以打电话

when( someArrayWithPromises ).done(function() {
});
Run Code Online (Sandbox Code Playgroud)

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