后端需要前端请求同一个接口三次,每次传参不同可以获取到不同的结果=>构成计算资源的选项。
其中一个接口传参获取数据报错,导致整个计算资源都没有可选择的options:
前端代码使用Promise.all获取res1, res2, res3返回结果,其中任意res报错就会导致没有选项:
Promise.all([
fetchStreamingResourceList({ xxx }),
fetchStreamingResourceList({ xxx }),
fetchStreamingResourceList({ xxx }),
])
.then(([res1, res2, res3]) => {
if (res1 && res2 && res3) {
option.push(
{ ...options[0], ...res1 },
{ ...options[1], ...res2 },
{ ...options[2], ...res3 },
)
setOptionList(option)
}
})
目标:当其他有任一接口报错,其他正常获取的接口应当出现在选项中,而不是全部不显示
promise状态:
pengding=>fulfilled
pending=>rejected
当需要处理多个Promise并行时,大多数情况下Promise.all很方便,但是遇上reject:
const delay = n => new Promise(resolve => setTimeout(resolve, n));
const promises = [
delay(100).then(() => 1),
delay(200).then(() => 2),
Promise.reject(3)
]
Promise.all(promises)
.then(values=>console.log(values))
.catch(err=>console.log(err))
// 加入catch语句后,最终输出:3,PromiseState:rejected
Promise.all能用catch捕获其中的异常,但发现其他执行成功的Promise的消息都丢失了,只返回一个最终状态:rejected。
要么全部成功,要么全部重来,这是Promise.all本身的强硬逻辑,也是痛点的来源。
假如使用Promise.allSettled来处理这段逻辑会怎样呢?
const promises = [
delay(100).then(() => 1),
delay(200).then(() => 2),
Promise.reject(3)
]
Promise.allSettled(promises).then(values=>console.log(values))
// 最终输出:
// [
// {status: "fulfilled", value: 1},
// {status: "fulfilled", value: 2},
// {status: "rejected", value: 3},
// ]
可以看到所有promise的数据都被包含在then语句中,且每个promise的返回值多了一个status字段,表示当前promise的状态,没有任何一个promise的信息被丢失。
当用Promise.allSettled时,我们只需专注在then语句里,当有promise被异常打断时,我们依然能妥善处理那些已经成功了的promise。
问题解决
Promise.allSettled([
xxx,
xxx,
xxx,
])
.then(results => {
for (const [index, result] of results.entries()) {
if (result.status === 'fulfilled' && result.value) {
option.push({ ...options[index], ...result.value });
}
}
}