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



我有以下返回 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. 在 forEach() 迭代的任何 promiseReturningFn() 拒绝的情况下,拒绝会被 catch() 语句捕获吗?

不,因为您没有在then回调中return承诺,而是在forEach回调中,而后者没有影响 - 这样的返回值在遗忘中丢失。

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

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

以下是您应该如何编码它,假设您允许在另一个尚未解析时已经在已解析的 promise 上执行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回调。

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

要对第二个问题回答"是",并在先前返回的承诺被拒绝时停止调用promiseReturningFn,您必须序列化它们,等待一个承诺实现,然后再调用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);
});
}

最新更新