承诺数组和Promise.all()

时间:2016-07-21 16:22:33

标签: javascript arrays angular promise zonejs

我有这样的Promises数组,如:

let promisesArray = [
    service1.load('blabla'),
    service2.load(), // throws an errors
];

我想执行它们并像这样抓住它们的错误

Promise.all(promisesArray)
    .then(() => doStuffs())
    .catch((err) => handleError(err));

这工作正常,但我现在想要在另一个承诺的then()中:

baseService()
    .then(() => Promise.all([
        service1.load('blabla'),
        service2.load(), // throw an errors
    ]))
    .catch((err) => handleError(err));
只要我直接在Promise.all()中编写数组,这个人的工作也很好,但是如果我想先使用promiseArray定义,那么:

baseService()
    .then(() => Promise.all(promisesArray))
    .catch((err) => handleError(err));

然后,catch()按预期运行,但我在控制台中出错

publish.js:45784 EXCEPTION: Error: Uncaught (in promise): ...

但我想使用最后一个解决方案,因为我的数组是根据某些条件通过将Promises推送到它而生成的。 (第一个例子工作正常,我没有得到不同的东西)

为我的每个承诺添加catch,同时将它们添加到数组中解决了我的问题,但我想找到更好的解决方案。

我真的很感激一些帮助。

PS:我正在使用带有zone.js的angular2,如果它改变了什么

3 个答案:

答案 0 :(得分:1)

一旦执行异步函数(返回一个promise),它就会开始在后台运行任务(kindof),承诺可以在您运行的那一刻随时解析或拒绝

let promisesArray = [
    service1.load('blabla'),
    service2.load(), // throws an errors
];

这些服务正在关闭并加载数据,如果它们在附加.then()之前返回,它们将保持其值并且一旦调用promisesArray [0] .then(x => console.log) (x))then函数将以该值

运行

但是,如果其中一个服务抛出错误并且还没有附加.catch函数,它们将保留错误以便将其发送到稍后指定的.catch()函数,但它们也会抛出一个控制台错误 - 因为他们不知道是否会附加一个catch函数,如果promises只是默默地失败并且错误消失,那将是令人沮丧的。

如果你真的希望你的promisesArray执行AFTER baseService(),那么你想让promisesArray成为一个启动异步任务并返回一个承诺的函数数组 - 是一个很好的想法。 但是传入一个返回promises数组的函数可能更好,而不是传递一个返回promise的函数数组(如上所述)

const getPromises = () => [
    service1.load('blabla'),
    service2.load(), // throws an errors
]

然后执行

baseService()
    .then(() => Promise.all(getPromises()))
    .catch((err) => handleError(err));

这只会在baseServce()完成后启动service1.load,并且所有错误都会在它们出现后立即被捕获

答案 1 :(得分:0)

由于您使用的是angular2,为什么不使用Observable和Http

var load1 = http.get('url1'),
    load2 = http.get('url2'),
    load3 = http.get('url3');

Observable.forkJoin(load1, load2, load2, function(res1, res2, res3){
    // manipulate your results here and return the reduced result

    return { whatever : { res1: res1, res2: res2, res3: res3 } }

}).
subscribe(function(finalResult){
     console.log(finalResult); // { whatever : { res1: res1, res2: res2, res3: res3 } }
});

答案 2 :(得分:0)

我想出了一种让它发挥作用的方法。

而不是一个promise数组我创建了一个返回Promise的函数数组:

let promisesArray = [
    () => service1.load('blabla'),
    () => service2.load(), // throws an errors
];
promisesArray.push(() => service2.load())

然后我使用Array.prototype.map()来运行Promise.all()中的承诺:

baseService()
    .then(() => Promise.all(promisesArray.map(promise => promise())))
    .catch((err) => handleError(err));

这解决了我的问题,不确定它是不是最好的方法。 如果有人有更好的想法,我会接受它。