我有以下返回 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);
});
}
关于这段代码,我有两个问题:
- 在
forEach()
迭代的任何promiseReturningFn()
拒绝的情况下,catch()
语句是否会捕获拒绝? - 如果第一次迭代的
promiseReturningFn()
被拒绝,迭代是否会停止,这意味着不会对结果数组中的第二个元素调用回调?如果为真,则在此失败后,控制流是否会传递给catch()
语句?
关于你的两个问题:
- 在 forEach() 迭代的任何 promiseReturningFn() 拒绝的情况下,拒绝会被 catch() 语句捕获吗?
不,因为您没有在then
回调中return
承诺,而是在forEach
回调中,而后者没有影响 - 这样的返回值在遗忘中丢失。
- 如果第一次迭代的 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);
});
}