Promise.all 缺陷
都知道 Promise.all 具有并发执行异步任务的能力。但它的最大问题就是如果其中某个任务出现异常(reject),所有任务都会挂掉,Promise 直接进入 reject 状态。
想象这个场景:你的页面有三个区域,分别对应三个独立的接口数据,使用 Promise.all 来并发三个接口,如果其中任意一个接口服务异常,状态是 reject,这会导致页面中该三个区域数据全都无法渲染出来,因为任何 reject 都会进入 catch 回调, 很明显,这是无法接受的,如下:
let a= new Promise((resolve,reject)=>{
//异步操作...
resolve({ code: 200,msg:"请求成功"})
})
let b= new Promise((resolve,reject)=>{
//异步操作...
resolve({ code: 200,msg:"请求成功"})
})
let c= new Promise((resolve,reject)=>{
//异步操作...
reject({ code: 500,msg:"服务器出现异常"})
})
//使用Promise.all 进行并发执行异步任务
Promise.all([a,b,c])
.then((res) => {
// 只有 上面所有的请求都是 resolve (成功) 的时候才会进入此回调中
console.log(res,"res")
})
.catch((error) => {
// 上面的请求中,只要有一个是reject (失败) 就会进入此回调
console.log(error,"error")
// error: {code: 500, msg: "服务异常"}
})
Promise.allSettled
当我们处理多个promise时,尤其是当它们相互依赖时,记录每个事件在调试中发生的错误可能很有用。使用Promise.allSettled,它会创建一个新的promise,在所有promise完成后返回一个包含每个promise结果的数组。
let a= new Promise((resolve,reject)=>{
//异步操作...
resolve({ code: 200,msg:"请求成功"})
})
let b= new Promise((resolve,reject)=>{
//异步操作...
resolve({ code: 200,msg:"请求成功"})
})
let c= new Promise((resolve,reject)=>{
//异步操作...
reject({ code: 500,msg:"服务器出现异常"})
})
//使用进行并发请求
Promise.allSettled([a,b,c]).then((data=>{
console.log(data,"data")
}))
//结果
[{"status":"fulfilled","value":{"code":200,"msg":"请求成功"}},{"status":"fulfilled","value":{"code":200,"msg":"请求成功"}},{"status":"rejected","reason":{"code":500,"msg":"服务器出现异常"}}]