如何避免相同的请求重复发送
2024-12-26 本文已影响0人
rainy66
export async function lodaData() {
const res = await request.get('/api/data')
return res.data
}
/*
* 完成 asyncOnce函数,函数接受一个异步函数作为参数,
返回一个新的函数,新的函数同时只能被调用一次,多次调用时返回第一次调用的结果。
*/
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))
})
})
}
}
//页面上调用这个函数,只会请求一次数据
export const getUseUser = asyncOnce(lodaData)
如果有参数的话该如何处理
export async function lodaData(id:number) {
const res = await request.get('/api/data',{params:{id}})
return res.data
}
/*
* 完成 asyncOnce函数,函数接受一个异步函数作为参数,
返回一个新的函数,新的函数同时只能被调用一次,多次调用时返回第一次调用的结果。
*/
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
})
})
}
}
//页面上调用这个函数,只会请求一次数据
export const getUseUser = asyncOnce(lodaData)
asyncOnce 函数内部定义了一个 map 对象,用于存储每个异步调用的状态。
当新函数被调用时,它首先检查 map 中是否已经存在当前调用参数的键(通过 JSON.stringify(args) 生成)。
如果不存在,说明这是第一次调用,将创建一个新的状态对象,并将 isPending 设置为 false。
然后,将调用者的 resolve 和 reject 函数分别添加到状态对象的 resolve 和 reject 数组中。
如果状态对象的 isPending 为 true,则表示异步操作正在进行中,直接返回,不重复执行异步操作。
如果 isPending 为 false,则开始执行异步操作,将 isPending 设置为 true。
异步操作完成后,使用 then 和 catch 分别处理成功和失败的情况,并将结果传递给所有等待的 resolve 和 reject 函数。
最后,在 finally 回调中,将 map 中的当前键值对设置为 null,以便释放资源。