首先來看看這四種方法是什么
Promise.all()
(MDN的定義)
- 描述:Promise.all() 方法接收一個promise的iterable類型(注:Array服傍,Map净嘀,Set都屬于ES6的iterable類型)的輸入官硝,并且只返回一個
Promise
實例矮固, 那個輸入的所有promise的resolve回調(diào)的結(jié)果是一個數(shù)組。這個Promise
的resolve回調(diào)執(zhí)行是在所有輸入的promise的resolve回調(diào)都結(jié)束盏袄,或者輸入的iterable里沒有promise了的時候崔拥。它的reject回調(diào)執(zhí)行是悔详,只要任何一個輸入的promise的reject回調(diào)執(zhí)行或者輸入不合法的promise就會立即拋出錯誤,并且reject的是第一個拋出的錯誤信息宰睡。 - 使用場景:當(dāng)我們需要等待多個返回值互不依賴的請求全部完成后再進(jìn)行下一步操作時蒲凶,就可以使用Promise.all()。就比如在訪問一個頁面的時候會調(diào)用多個接口查詢數(shù)據(jù)拆内,在c查詢的時候旋圆,頁面上會顯示loading,等接口都返回了再隱藏掉loading。
Promise.race()
(MDN的定義)
- 描述:Promise.race(iterable) 方法返回一個 promise麸恍,一旦迭代器中的某個promise解決或拒絕灵巧,返回的 promise就會解決或拒絕搀矫。
- 使用場景:我們可以利用Promise.race來模擬超時,寫一個定時器刻肄,到時間就提示用戶超時瓤球,將請求接口的函數(shù)和這個定時器都放到Promise.race中去,如果接口在定時器計時結(jié)束之后返回的話敏弃,就會拋出超時的提示卦羡。
Promise.retry()
- 描述:Promise.retry()在官方?jīng)]有封裝,但是在我們?nèi)粘i_發(fā)的時候使用的很多麦到,所以我們一般會自己封裝Promise.retry绿饵。它實現(xiàn)了失敗后重新嘗試的功能。這個方法接收一個綁定函數(shù)隅要、重試次數(shù)蝴罪、延遲時間
- 使用場景:超時重試
Promise.allSettled()
(MDN的定義)
- 描述:Promise.allSettled()方法返回一個在所有給定的promise都已經(jīng)fulfilled或rejected后的promise,并帶有一個對象數(shù)組步清,每個對象表示對應(yīng)的promise結(jié)果要门。
- 使用場景:allSettled不論最后的結(jié)果是fulfilled還是rejected,都會將結(jié)果存入返回的數(shù)組里廓啊,適用于多個彼此不依賴的異步任務(wù)成功完成時欢搜,或者你想知道每個promise的結(jié)果時
現(xiàn)在我們自己來實現(xiàn)這四種方法
Promise.all()
Promise.all = function(promises){
return new Promise((resolve,reject)=>{
let result = []
let counter = 0
for(let i = 0;i<promises.length;i++){
// 以防不是promise對象所以用resolve包一下
Promise.resolve(promises[i]).then(res=>{
//為了讓返回的結(jié)果按順序排列,這里不能使用result.push
result[i] = res
if(++counter===promises.length){
return resolve(result)
}
},(err)=>{
return reject(err)
})
}
})
}
Promise.race
Promise.race = function(promises){
return new Promise((resolve,reject)=>{
for(item of promises){
Promise.resolve(item).then((res)=>{
resolve(res)
},err=>reject(err))
}
})
}
Promise.retry
/**
* @description: 加入失敗后使用失敗重試功能谴轮,如果5次中有任意一次成功了炒瘟,就停止嘗試并返回
* @param {*}
* @return {*}
* @param {*} fn 綁定函數(shù)
* @param {*} times 請求次數(shù)
* @param {*} delay 延遲時間
*/
Promise.retry = function(fn,times,delay){
let tryTimes = 0
return new Promise((resolve,reject)=>{
function attempt(){
console.log(tryTimes)
Promise.resolve(fn()).then(res=>{
return resolve(res)
}).catch(err=>{
if(++tryTimes<times){
setTimeout(attempt,delay)
}else{
return reject(err)
}
})
}
attempt()
})
}
Promise.allSettled
- 在Promise.all的基礎(chǔ)上實現(xiàn)·
function allSettled(promises){
//只需要把rejected的情況捕獲一下,并返回一個正常值第步,狀態(tài)就會進(jìn)入到fulFilled
return Promise.all(promises.map(item=>Promise.resolve(item)
.then(res=>({status:'fulfilled',value:res}),
err=>({status:'rejected',reason:err}))
))
}
- 不基于Promise.all
function allSettled(promises){
return new Promise((resolve)=>{
promises = Array.isArray(promises)?promises:[]
let count = promises.length
let result = []
for(let i = 0;i < promises.length; i++){
Promise.resolve(promises[i]).then(res=>result[i]={status:'fulfilled',value:res},
err=>result[i] = {status:'rejected',reason:err})
.finally(()=>{
if(--count<=0){
resolve(result)
}
})
}
})
}