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":"服務器出現異常"}}]