首先來看看這四種方法是什么
Promise.all()(MDN的定義)
- 描述:Promise.all() 方法接收一個(gè)promise的iterable類型(注:Array,Map,Set都屬于ES6的iterable類型)的輸入,并且只返回一個(gè)
Promise實(shí)例, 那個(gè)輸入的所有promise的resolve回調(diào)的結(jié)果是一個(gè)數(shù)組。這個(gè)Promise的resolve回調(diào)執(zhí)行是在所有輸入的promise的resolve回調(diào)都結(jié)束,或者輸入的iterable里沒有promise了的時(shí)候。它的reject回調(diào)執(zhí)行是,只要任何一個(gè)輸入的promise的reject回調(diào)執(zhí)行或者輸入不合法的promise就會(huì)立即拋出錯(cuò)誤,并且reject的是第一個(gè)拋出的錯(cuò)誤信息。 - 使用場景:當(dāng)我們需要等待多個(gè)返回值互不依賴的請(qǐng)求全部完成后再進(jìn)行下一步操作時(shí),就可以使用Promise.all()。就比如在訪問一個(gè)頁面的時(shí)候會(huì)調(diào)用多個(gè)接口查詢數(shù)據(jù),在c查詢的時(shí)候,頁面上會(huì)顯示loading,等接口都返回了再隱藏掉loading。
Promise.race()(MDN的定義)
- 描述:Promise.race(iterable) 方法返回一個(gè) promise,一旦迭代器中的某個(gè)promise解決或拒絕,返回的 promise就會(huì)解決或拒絕。
- 使用場景:我們可以利用Promise.race來模擬超時(shí),寫一個(gè)定時(shí)器,到時(shí)間就提示用戶超時(shí),將請(qǐng)求接口的函數(shù)和這個(gè)定時(shí)器都放到Promise.race中去,如果接口在定時(shí)器計(jì)時(shí)結(jié)束之后返回的話,就會(huì)拋出超時(shí)的提示。
Promise.retry()
- 描述:Promise.retry()在官方?jīng)]有封裝,但是在我們?nèi)粘i_發(fā)的時(shí)候使用的很多,所以我們一般會(huì)自己封裝Promise.retry。它實(shí)現(xiàn)了失敗后重新嘗試的功能。這個(gè)方法接收一個(gè)綁定函數(shù)、重試次數(shù)、延遲時(shí)間
- 使用場景:超時(shí)重試
Promise.allSettled()(MDN的定義)
- 描述:Promise.allSettled()方法返回一個(gè)在所有給定的promise都已經(jīng)fulfilled或rejected后的promise,并帶有一個(gè)對(duì)象數(shù)組,每個(gè)對(duì)象表示對(duì)應(yīng)的promise結(jié)果。
- 使用場景:allSettled不論最后的結(jié)果是fulfilled還是rejected,都會(huì)將結(jié)果存入返回的數(shù)組里,適用于多個(gè)彼此不依賴的異步任務(wù)成功完成時(shí),或者你想知道每個(gè)promise的結(jié)果時(shí)
現(xiàn)在我們自己來實(shí)現(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對(duì)象所以用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 請(qǐng)求次數(shù)
* @param {*} delay 延遲時(shí)間
*/
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ǔ)上實(shí)現(xiàn)·
function allSettled(promises){
//只需要把rejected的情況捕獲一下,并返回一個(gè)正常值,狀態(tài)就會(huì)進(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)
}
})
}
})
}