1

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

这是我的代码:

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 被拒绝解决,这个结果 Promise 将被同样的拒绝解决。

然后我会用

getPages.then(getEvents)

wheregetEvents是另一个函数,它需要一个数组,其中的元素由getPages.

谁能帮我吗?谢谢!

4

3 回答 3

8

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

function all(arrayOfPromises) {
    return jQuery.when.apply(jQuery, arrayOfPromises).then(function() {
        return Array.prototype.slice.call(arguments, 0);
    });
};

这需要解决两个问题:

  1. 不是接受一个数组,而是接受jQuery.when可变数量的参数,所以我们必须调用它apply来给它我们的承诺数组。
  2. 组合的 Promise 用多个参数解决,而不是单个数组参数,所以我们必须arguments变成一个真正的数组(使用slice)。

因此:

var getAnimal = function(animal) {
    return $.get('animals/' + animal);
};

var arrayOfPromisesToAnimals = ['frog', 'cat', 'horse'].map(getAnimal);

var promiseToArrayOfAnimals = all(arrayOfPromisesToAnimals);

promiseToArrayOfAnimals.then(function(arrayOfAnimals) {

    arrayOfAnimals.forEach(function(animal) {
        console.log(animal);
    });
});
于 2013-09-13T10:57:59.313 回答
2

如果您使用的是Q,那么只需执行以下操作:

Q.all(promises)

这通常比使用 jQuery 来实现你的承诺要好得多,因为 Q 的设计要好得多。此外,给Q.alljQuery 承诺是安全的,它会很好地吸收它们。

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

于 2013-04-25T13:15:13.120 回答
0

wherepromises是一个数组,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 集合。

于 2013-04-25T22:24:06.470 回答