为什么要做本地缓存
在本地缓存部分变动频率极低的数据,可以有效提高页面的响应速度,但需要注意不能长期保存否则会与实际产生偏差
基础方法
const copyObj = (body) => JSON.parse(JSON.stringify(body))
对一个对象进行克隆,目的是让他们的引用脱钩,防止在 a = b 之后修改a导致b的变化。
核心逻辑
export const getCache = ({
cacheObj, key, requestMethod, force = false, useCache, saveCache, loadCache}) => {
const cache = cacheObj[key]
//当缓存中有数据,且不是强制模式,且useCache判断数据可用时,返回缓存中的数据
if (!force && cache && (!useCache || useCache(cache))) {
console.log("从缓存读取数据 " + key)
const body = copyObj(loadCache ? loadCache(cache) : cache);
return new Promise((r) => r(body))
}
//否则发送网络请求,请求成功后将数据保存到缓存对象中
return requestMethod().then(body => {
console.log("数据写入缓存 " + key)
if (saveCache) {
saveCache(cacheObj, key, body)
} else {
cacheObj[key] = body
}
return copyObj(body);
})
}
缓存保存和提取的方法,基本流程:当执行本方法时,先检查保存缓存数据的对象,看是否存在先前缓存的数据,缓存的数据是否过期,如果符合要求的话则直接从中取出数据返回;如果不符合要求则发送网络请求获取一份新数据,成功获取数据之后保存到缓存对象中。
方法参数含义:
- cacheObj :缓存对象,本例中它应该是 Vuex 的 state中的一个对象
- key : 在缓存对象中保存数据的字段名,如果你的查询方法使用到一些参数,应该使用这些参数来生成一个唯一的key
- requestMethod:发送网络请求的方法,注意它应该返回一个 Promise 对象。
- force:当设置为 true 时,忽略缓存检查流程直接走发送请求的逻辑。
- useCache:可以传入一个方法,将会把缓存中的数据传入,应该返回一个 boolean值,表示该数据是否还可用。如果不配置该项,相当于永远 true 。
- saveCache:可以传入一个方法,会将 cacheObj , key , 请求到的数据 传入,规定了数据在缓存对象中的保存方式 ,如果不配置该项,默认为 cacheObj[key] = body
- loadCache:可以传入一个方法,将会把缓存中的数据传入,规定了缓存数据的读取方式。如果不配置该项,默认为原样返回。saveCache 和 loadCache 应该成对配置并执行相反的操作。
按时间过期形式的缓存
export const getCacheByTime = ({
cacheObj, key, requestMethod, force = false, seconds}) => {
const now = Math.floor(new Date().getTime() / 1000)
return getCache({
cacheObj, key, requestMethod, force,
useCache: (cache) => now - cache.time < seconds,
saveCache: (cacheObj, key, body) => cacheObj[key] = {
data: body, time: now},
loadCache: (cache) => cache.data,
})
}
这里直接调用了核心方法,但是对参数进行了精简。cacheObj, key, requestMethod, force,原样传递,但是配置了 useCache, saveCache, loadCache 三个方法。
参数含义:
- seconds:当当前时间与拿到缓存数据的时间超过一定秒数之后,认为该数据不再可用,应重新请求。
- saveCache:规定了数据保存方式为在原数据上加一层壳,将当前时间一并保存
- loadCache:规定了数据的读取方式为展开一层壳,因为原数据被保存到了data字段里
- useCache:规定了数据可用性的判断规则为比较数据的获取时间和当前时间,不能超过指定值。
在Vuex中使用该方法:
state: {
cache:{
},
},
actions: {
getDetail: ({
dispatch, commit, state}, {
uuid, force}) => {
return getCacheByTime({
cacheObj: state.cache, force,
key: `设备详情 ${
uuid}`,
seconds: 60,
requestMethod: () => getDeviceInventoryDetail(uuid)
})
},
}
在vue组件中使用该Vuex方法
import {
mapActions} from "vuex";
methods: {
...mapActions('Device', ['getDetail']),
test(){
this.getDetail(uuid).then(res=>{
//xxxxxxxx
})
},
}
缓存刷新
一般来说,当执行了任何的 增、删、改操作之后就应该刷新(清空)缓存,否则前端显示数据会与实际不一致,可以在 vuex 的 mutations 字段里定义一个清空方法 ,在增删改请求成功后调用即可