axios是常用的http请求库,利用adapter我们给请求加上缓存以方便提高性能
const createCacheAxios = () => {
const caches = {}
//清理过期缓存
setInterval(()=>{
Object.keys(caches).forEach(key => {
const cache = caches[key]
if (cache && !cache.pending && new Date()-cache.timestamp > cache.expires) delete caches[key]
})
},1000*60)
return axios.create({
adapter(config) {
const { method = 'get', data, params, url, expires } = config
const key = JSON.stringify({ url, method, data, params })
return new Promise((resolve, reject) => {
//回调任务
const resolveTask = (res) => {
const cache = caches[key]
if (cache) {
cache.resolveTask.forEach(cb => cb(res))
Object.assign(cache, { pending: false, resolveTask: [], rejectTask: [], value: res })
}
}
//异常任务
const rejectTask = (res) => {
const cache = caches[key]
if (cache) {
cache.rejectTask.forEach(cb => cb(res))
delete caches[key]
}
}
//原始请求
const orginRequest=(resolve,reject)=>{
delete config.adapter
axios(config).then(resolve).catch(reject)
}
//缓存回调并请求
const cacheAndRequest=()=>{
caches[key] = { timestamp: new Date(), expires, pending: true, resolveTask: [resolve], rejectTask: [reject] }
orginRequest(resolveTask,rejectTask)
}
//不需要缓存
if (!expires) {
orginRequest(resolve,reject)
return
}
const cache = caches[key]
//尚未缓存
if (!cache) {
cacheAndRequest()
return
}
//缓存且在请求中
if (cache.pending) {
cache.resolveTask.push(resolve)
cache.rejectTask.push(reject)
return
}
//缓存过期
if(new Date() - cache.timestamp > cache.expires){
cacheAndRequest()
return
}
//已有缓存结果
resolve(cache.value)
})
}
})
}
使用方式如下:
const instance=createCacheAxios()
const get=()=>{
return instance.get('./data.json',{expires:1000*60})
}
get().then(res=>{
console.log('res',res)
})
get().then(res=>{
console.log('res',res)
})
输出如下:
可以看到两次调用两次输出,只进行了一次请求,进行错误调用测试如下:
const instance=createCacheAxios()
const get=()=>{
return instance.get('./data2.json',{expires:1000*60})
}
get().then(res=>{
console.log('res',res)
}).catch(res=>{
console.log('err1',res)
})
get().then(res=>{
console.log('res',res)
}).catch(res=>{
console.log('err2',res)
})
输出如下:
可以看到两次错误调用两次错误输出,只进行了一次请求