大家都知道 Promise.all 传入的 promise array 里面,只要有其中一个 promise reject 了,即使它前面的 promise 正常 fulfilled,整个 promise.all 也会直接走到 catch,并且只会 catch 第一个 reject 的返回值。
那如何让一串 promise 用 Promise.all 实现并行不阻塞地调用,同时每个的 reject 和 fulfilled 状态不互相影响呢?
答案是将这串 promise,每个都用一个新 promise 包裹一下。无论内部原 promise 抛出 reject 还是 fulfilled ,都用外层的 promise resolve 返回。
resolve 返回的信息里再自定义字段来传递原 promise 的成功失败和返回内容即可。
将包裹后的各个 promise 放入 promise.all 中,自然可以保证每个都不会 reject,同时达到并行不阻塞的目的。
示例代码如下:
改造前代码:
// Promise.all 调用:只要其中一个报错,就得到 [undefined, undefined, undefined]
const [res1, res2, res3] = await Promise.all([
somePromise1,
somePromise2,
somePromise3
])
改造后代码:
// 包裹函数,避免 promise 抛出 reject
const wrapPromise = (promise)=> {
return new Promise((resolve, reject) => {
promise
.then((info) => resolve({ isok: true, info }))
.catch((err) => resolve({ isok: false, err }))
})
}
// Promise.all 调用
const resArr = await Promise.all([
// 全部使用 wrapPromise 包裹
wrapPromise(somePromise1),
wrapPromise(somePromise2),
wrapPromise(somePromise3)
])
const [res1, res2, res3] = resArr.map((res) => {
if (res.isok) {
// 处理 fulfilled promise 结果的逻辑
return res.info
} else {
// 处理 rejected promise 结果的逻辑
console.error(res.err)
return {}
}
})