【问题标题】:What is cleanest way to turn Array of JQuery Promises into a JQuery Promise of an Array?将 JQuery Promise 数组转换为数组的 JQuery Promise 的最简洁方法是什么?
【发布时间】:2012-08-25 18:32:01
【问题描述】:

我遇到了一个数组中有多个 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

我目前在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;
  });
};

Here is a jsFiddle 我正在寻找的结果。

我想知道是否有更好(更短、更简洁)的方式来定义 someTransform 以达到相同的结果?

【问题讨论】:

标签: javascript jquery coffeescript promise


【解决方案1】:

您可以只将apply 数组作为$.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 to do it

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

【讨论】:

  • 我认为 OP 实际上是在寻求一种“更短、更清洁”的方式,并且已经意识到 .apply()
  • 我会让问题更清楚,但我相信这将通过result1,result2,... 完成调用,但我希望使用[result1,result2,...] 的单个参数完成调用,请参阅jsfiddle.net/qk2mT/2“抛出对象 0 没有方法“加入”“
  • @Soldier.moth:done 处理程序没有得到结果数组;相反,它会传递 n 个参数,其中 n 是您最初传入的 Deferred 数量。使用隐式 arguments 对象循环遍历结果。
  • @josh3736:是的,我希望有一个很好的方法可以为我将arguments 转换为数组。可以通过定义 $.whenall 来完成,例如 function(arr) { return $.when.apply($,arr).pipe(function(){ return [].slice.call(arguments,0); }); }
  • @Soldier.moth:是的,可以。我会使用Array.prototype.slice 而不是[],这样您就不会不必要地创建一个 Array 实例。查看更新。
【解决方案2】:

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

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

现在,我们可以打电话了

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

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

【讨论】:

猜你喜欢
  • 2010-12-23
  • 1970-01-01
  • 2013-04-19
  • 2012-02-05
  • 1970-01-01
  • 2019-05-19
相关资源
最近更新 更多