arr.forEach() 语句的回调中的承诺拒绝会停止迭代吗?

Will a promise rejection within the callback of an arr.forEach() statement stop the iteration?

我有以下功能 returns Promise:

function someFn() {
    // Making use of Bluebird's Promise.all()
    return Promise.all([promise1, promise2]).then(function(results) {
        results.forEach(function(result) {
            return promiseReturningFn();  // Returns a Promise
        });
    }).catch(function(err) {
        console.log(err);
    });
}

关于这段代码我有两个问题:

  1. 在任何 forEach() 迭代的 promiseReturningFn() 拒绝的情况下,拒绝是否会被 catch() 语句捕获?
  2. 如果第一次迭代的promiseReturningFn()拒绝,迭代会停止吗,意味着不会为结果数组中的第二个元素调用回调?如果这是真的,那么在这次失败之后控制流是否会传递给 catch() 语句?

关于你的两个问题:

  1. In a scenario where any of the forEach() iteration's promiseReturningFn() rejects, will the rejection be caught by the catch() statement?

不,因为你没有在 then 回调中 return 一个 promise,而是在 forEach 回调中,后者没有任何效果——这样一个 return 价值被遗忘。

  1. If the first iteration's promiseReturningFn() rejects, will the iteration stop, meaning that the callback will not be called for the second element in the results array? If this is true, will control flow be passed to the catch() statement after this failure?

不,迭代不会停止。您甚至不知道同步拒绝,因为此信息只能异步可用(暂时忽略 bluebird 允许同步检查)。

假设您允许 promiseReturningFn 已在已解决的承诺上执行,而另一个尚未解决:

function someFn() {
    // Making use of Bluebird's Promise.all()
    return Promise.all(
        [promise1, promise2].map(p => p.then(promiseReturningFn))
    }).catch(function(err) {
        console.log(err);
    });
}

或者,如果你真的需要在开始为它们执行 promiseReturningFn 之前解决所有的承诺数组,那么这样做:

function someFn() {
    // Making use of Bluebird's Promise.all()
    return Promise.all([promise1, promise2]).then(results => {
        return Promise.all(results.map(promiseReturningFn));
    }).catch(function(err) {
        console.log(err);
    });
}

无论哪种情况,您的两个问题的答案现在是:

  • 是的,如果任一内部承诺拒绝,将执行 catch 回调。

  • 不,迭代不会停止,因为 promise 的结果只能异步知道,所以到那时循环 (map) 已经完全执行了。

要回答 "Yes" 第二个问题并停止调用 promiseReturningFn 当先前的 returned 承诺被拒绝时,您必须序列化它们,等待一个承诺在再次调用 promiseReturningFn 之前完成:

function someFn() {
    // Making use of Bluebird's Promise.all()
    return Promise.all([promise1, promise2]).then(results => {
        return (function loop(i, p) {
            return i >= results.length ? p
                : p.then(_ => loop(i+1, promiseReturningFn(result[i])));
        })(0, Promise.resolve());
    }).catch(function(err) {
        console.log(err);
    });
}