如何将promise对象数组转换为数组的promise对象?

时间:2013-04-25 11:20:38

标签: jquery promise q

有没有办法将promise对象数组转换为数组的promise对象?我在AngularJS中寻找的行为类似于$q.all(promises)

这是我的代码:

var getPages = function(courses) {
  var courses_promises = courses.filter(function(item) {
    return item.courses[0].home_link;
  }).map(function(item) {
    deferred = $.Deferred();
    item["class_link"] = item.courses[0].home_link;
    item["home_link"] = item["class_link"] + "class/index";
    $.get(item.home_link)
       .then(function(response) {
        item["html"] = response;
        deferred.resolve(item);
       });
    return deferred.promise();
  });
  return $.when.apply($, courses_promises);
};  

我希望getPages函数返回一个将使用值数组解析的单个promise,每个值对应于promises数组中相同索引处的promise。如果任何承诺通过拒绝得到解决,那么这个承诺将以相同的拒绝解决。

然后我会用

getPages.then(getEvents)

其中getEvents是另一个函数,它期望一个数组的元素由getPages解析。

任何人都可以帮助我吗?谢谢!

3 个答案:

答案 0 :(得分:8)

对于那些不想进入另一个库的人(虽然我可以确认Q很好,似乎是节点的最佳承诺系统),这里是使用jQuery {{1}的Q.all的实现。 }:

when

这需要考虑两个问题:

  1. function all(arrayOfPromises) { return jQuery.when.apply(jQuery, arrayOfPromises).then(function() { return Array.prototype.slice.call(arguments, 0); }); }; 不是接受数组,而是接受可变数量的参数,因此我们必须使用jQuery.when调用它来为它提供我们的承诺数组。
  2. 使用多个参数解决组合的promise,而不是单个数组参数,因此我们必须将apply转换为实数数组(使用arguments)。
  3. 因此:

    slice

答案 1 :(得分:2)

如果您正在使用Q,请执行以下操作:

Q.all(promises)

这通常是比使用jQuery更好的想法,因为Q有更好的设计。另外,给Q.all jQuery承诺是安全的,它会很好地吸收它们。

如果您不想使用Q,我相信$.when会做类似的事情,但它并不是那么干净简单。

答案 2 :(得分:0)

promises是一个数组,jQuery相当于Q.all(promises)是:

jQuery.when.apply(null, promises);

许多jQuery程序员在同意这一点时使用它是笨拙的。 jQuery.when()接受数组会更好。

修改

现在我已经看到了完整的getPages函数,我可以更好地建议jQuery解决方案:

我认为这很简单:

var getPages = function(courses) {
    var promises = courses.map(function(c) {
        if(!c.courses[0].home_link) return null;//filter action
        return $.get(c.courses[0].home_link + "class/index").done(function(response) {
            c.html = response;
        });
    }).get();//Remove jQuery wrapper to reveal an array of jqXHR promises.
    return $.when.apply($, promises);
};

$.when.apply($, promises)行总是正确的。您只需要确保promises是一个真正的javascript数组,而不是jQuery集合。

相关问题