在前端开发中,有时带有缓存功能的fetch请求可以提高性能,以前曾写过一篇帖子异步缓存-cacheCall,那个里面是通过回调获取返回值,现在promise大行其道,这次封装的函数通过promise.resole获取返回值,普通的fetch请求如下:
const get = ({ url }) => {
return fetch(url).then(res=>res.json())
}
我们通过cacheCall函数可以对上述函数进行包裹处理,使其具有cache功能
//fn:不带cache功能返回promise的函数,interval:缓存有效期,单位ms
const cacheCall = (fn, interval) => {
const caches = {}
setInterval(() => {
Object.keys(caches).forEach(key => {
const cache = caches[key]
if (cache && !cache.pending && new Date() - cache.time > interval) delete caches[key]
})
}, 60 * 1000)
return (arg) => {
const key = JSON.stringify(arg)
return new Promise((resole, reject) => {
const resoleTask=(res)=>{
const cache = caches[key]
cache.resoleTask.forEach(cb => cb(res))
Object.assign(cache, { resoleTask: [],rejectTask:[], value:res, time: new Date(), pending: false })
}
const rejectTask=(res)=>{
const cache = caches[key]
cache.rejectTask.forEach(cb => cb(res))
delete caches[key]
}
const cache = caches[key]
if (cache) {
cache.pending ? (cache.resoleTask.push(resole),cache.rejectTask.push(reject)) : resole(cache.value)
} else {
caches[key] ={ pending: true, resoleTask: [resole],rejectTask:[reject] }
fn(arg).then(resoleTask).catch(rejectTask)
}
})
}
}
调用例子如下:
const url = './data.json'
const cacheGet = cacheCall(get, 1000 * 60)
cacheGet({ url }).then(res => {
console.log(res)
})
cacheGet({ url }).then(res => {
console.log(res)
})
测试结果如下:
可以看出两次调用输出了两次结果,但是只做了一次http请求,我们故意进行错误调用看会发生什么
const url = './data2.json'
const cacheGet = cacheCall(get, 1000 * 60)
cacheGet({ url }).then(res => {
console.log(res)
}).catch(res=>{
console.log('err1',res)
})
cacheGet({ url }).then(res => {
console.log(res)
}).catch(res=>{
console.log('err2',res)
})
可以看出两次错误调用输出了两次结果,只做了一次http请求