15

我遇到了一个数组中有多个 JQuery Promise 的情况

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

并且需要把它变成一个数组的 JQuery Promise

var promiseOfArray = someTransform(arrayOfPromises)

在哪里

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

创建带有文本的警报

结果1,结果2,结果3,结果4

我目前在咖啡脚本中定义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来实现相同的结果?

4

2 回答 2

35

您可以数组作为参数应用到$.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]
    }
});

如果你真的只想加入所有延迟的字符串结果,我们可以使用一个小数组黑客。 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);
    });
};
于 2012-08-30T23:12:55.307 回答
6

$.when.apply当我们需要在多个 Promise 上调用它时,总是输入“丑陋”的行也让我很困扰。但是Function.prototype.bind为了救命!

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

现在,我们可以打电话

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

Function.prototype.bind是 ES5 的一部分,并且可以在浏览器中广泛使用。如果您还需要支持非常旧的浏览器,则有大量简单的shims可用

于 2012-08-30T23:15:52.183 回答