Promise.all/Promise.race/Promise.retry/Promise.allSettled原理實(shí)現(xiàn)

首先來看看這四種方法是什么

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)
                }
            })
        }
    })
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容