如何避免相同的請求重復(fù)發(fā)送

export async function lodaData() {
  const res =  await request.get('/api/data')
  return res.data
}

/*
* 完成 asyncOnce函數(shù),函數(shù)接受一個(gè)異步函數(shù)作為參數(shù),
返回一個(gè)新的函數(shù),新的函數(shù)同時(shí)只能被調(diào)用一次,多次調(diào)用時(shí)返回第一次調(diào)用的結(jié)果。
 */

export function asyncOnce(cb:(...args:any[])=>Promise<any>){
  let isPending = false
  const stack:any[] = []
  return () => {
    return new Promise((resolve,reject) => {
      if(isPending) {
        stack.push(resolve,reject)
        return
      }
      isPending = true
      cb().then((res) => {
        resolve(res)
        stack.forEach(({resolve})=>resolve(res))
      }).catch((err) => {
        reject(err)
        stack.forEach(({reject})=>reject(err))
      })
    })
  }
}

//頁面上調(diào)用這個(gè)函數(shù),只會(huì)請求一次數(shù)據(jù)
export const getUseUser = asyncOnce(lodaData)

如果有參數(shù)的話該如何處理

export async function lodaData(id:number) {
  const res =  await request.get('/api/data',{params:{id}})
  return res.data
}

/*
* 完成 asyncOnce函數(shù),函數(shù)接受一個(gè)異步函數(shù)作為參數(shù),
返回一個(gè)新的函數(shù),新的函數(shù)同時(shí)只能被調(diào)用一次,多次調(diào)用時(shí)返回第一次調(diào)用的結(jié)果。
*/

export function asyncOnce(cb:(...args:any[])=>Promise<any>){
  const map:Record<string,{
    resolve:((value: any) => void)[],
    reject:((err?: any) => void)[],
    isPending:boolean
  } | null> = {}
  return(...args:any[]) => {
    return new Promise((resolve,reject) => {
      const key = JSON.stringify(args)
      if(!map[key]){
        map[key] = {
          resolve:[],
          reject:[],
          isPending:false
        }
      }
      const state = map[key]
      state.resolve.push(resolve)
      state.reject.push(reject)
      if(state.isPending)return
      state.isPending = true
      cb(...args).then((res) => {
        state.resolve.forEach(resolve => resolve(res))
      }).catch((err) => {
        state.reject.forEach(reject => reject(err))
      }).finally(()=>{
        map[key] = null
      })
    })
  }
}
//頁面上調(diào)用這個(gè)函數(shù),只會(huì)請求一次數(shù)據(jù)
export const getUseUser = asyncOnce(lodaData)

asyncOnce 函數(shù)內(nèi)部定義了一個(gè) map 對象,用于存儲(chǔ)每個(gè)異步調(diào)用的狀態(tài)。
當(dāng)新函數(shù)被調(diào)用時(shí),它首先檢查 map 中是否已經(jīng)存在當(dāng)前調(diào)用參數(shù)的鍵(通過 JSON.stringify(args) 生成)。
如果不存在,說明這是第一次調(diào)用,將創(chuàng)建一個(gè)新的狀態(tài)對象,并將 isPending 設(shè)置為 false。
然后,將調(diào)用者的 resolve 和 reject 函數(shù)分別添加到狀態(tài)對象的 resolve 和 reject 數(shù)組中。
如果狀態(tài)對象的 isPending 為 true,則表示異步操作正在進(jìn)行中,直接返回,不重復(fù)執(zhí)行異步操作。
如果 isPending 為 false,則開始執(zhí)行異步操作,將 isPending 設(shè)置為 true。
異步操作完成后,使用 then 和 catch 分別處理成功和失敗的情況,并將結(jié)果傳遞給所有等待的 resolve 和 reject 函數(shù)。
最后,在 finally 回調(diào)中,將 map 中的當(dāng)前鍵值對設(shè)置為 null,以便釋放資源。

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

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

  • 1.Typescript中的&理解 參數(shù)中的 & 表示props對象同時(shí)擁有了TagManagementState...
    Lethe35閱讀 7,813評論 0 1
  • 22. 如何判斷一個(gè)對象是否屬于某個(gè)類? ●第一種方式,使用 instanceof 運(yùn)算符來判斷構(gòu)造函數(shù)的 pro...
    稚沅閱讀 179評論 0 0
  • ECMAScript 是一種由 Ecma 國際(前身為歐洲計(jì)算機(jī)制造商協(xié)會(huì))通過 ECMA-262 標(biāo)準(zhǔn)化的腳本程...
    歡欣的膜笛閱讀 8,750評論 0 4
  • 入門與進(jìn)階 第一章 進(jìn)入編程 1,如何快速運(yùn)行一段js代碼? 方式1:瀏覽器開發(fā)者工具??梢允褂每旖萱Ioption...
    瀟瀟瀟瀟瀟瀟瀟閱讀 941評論 0 0
  • 1、項(xiàng)目中亮點(diǎn)(難點(diǎn)) 在項(xiàng)目中用ECharts畫的可視化大屏的時(shí)候,里面的字體在調(diào)整瀏覽器大小的時(shí)候無法做到適配...
    f360f8fc4fbb閱讀 123評論 0 0

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