异步缓存3-cacheAxios

523 阅读1分钟

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)
})

输出如下:

image.png

可以看到两次调用两次输出,只进行了一次请求,进行错误调用测试如下:

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)
})

输出如下:

image.png

可以看到两次错误调用两次错误输出,只进行了一次请求