【问题标题】:array of promises and Promise.all()承诺数组和 Promise.all()
【发布时间】:2016-11-25 08:34:18
【问题描述】:

我有这样的 Promise 数组:

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 添加到我的每个 promise 中,同时将它们添加到数组中可以解决我的问题,但我想找到一个更好的解决方案。

我真的很感谢你的帮助。

PS:如果有变化,我将 angular2 与 zone.js 一起使用

【问题讨论】:

  • 请告诉我们你是如何创建promisesArray的。也许看看this

标签: javascript arrays angular promise zonejs


【解决方案1】:

一旦你执行了一个异步函数(一个返回承诺的函数),它就会开始在后台运行任务(kindof),从你运行的那一刻起,承诺可能会随时解决或拒绝

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

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

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

如果您真的希望您的 promisesArray 在 baseService() 之后执行,那么您将 promisesArray 设为启动异步任务并返回 promise 的函数数组的想法是一个不错的想法。 然而,传入一个返回承诺数组的函数可能会更好,而不是传入一个返回承诺的函数数组(如上所述)

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

然后使用执行

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

这只会在 baseServce() 完成后启动你的 service1.load,所有错误都会在它们发生后立即被捕获

【讨论】:

    【解决方案2】:

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

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

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

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

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

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

    【讨论】:

    • 如果这是一个解决方案(我不知道问题所在),至少不要称它为 promisesArray 而是 factoryArrayactionsArrayloadFns 或任何合适的名称。
    • 或者,只需声明一个返回承诺数组的函数,这可能是一个更好的主意。
    【解决方案3】:

    既然你在使用 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 } }
    });
    

    【讨论】:

    • 这将避免我的问题,但这将是对我的服务的相当大的改变。我宁愿在保持 Promise 的同时修复它——我真的很想了解最后两个示例之间的实际不同。
    猜你喜欢
    • 2017-05-17
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    • 2019-01-05
    • 2020-04-24
    • 2022-08-20
    • 2020-02-29
    相关资源
    最近更新 更多