功能概述:
- 前端项目中有同一接口重复触发的并发现象
- 一些公共数据接口,如用户信息,配置信息等接口需要多次获取
- 首页有大量重复请求影响启动时间
适用条件:
- 基本的公共数据和用户信息
- get类获取数据接口
- 基本原则就是缓存不更新或者更新周期较长的数据
大体思路:
- 初次请求时将接口promise缓存到map对象中,map中的key名使用api名+参数拼接;下一次请求到同一key名的接口直接返回缓存中的promise;如果没有此key的promise使用正常的接口请求;
需求功能:
- 同一个接口,需要区分参数进行存储接口名+参数,生成唯一字符串
- 支持异步接口请求
- 支持promise
- 考虑并发的情况,同一接口同时触发的情况
- 默认关闭缓存,通过接口参数设置单独开启缓存
- 支持设置有效期,过期主动清除,取代惰性删除可能引起的内存溢出
实现代码:
class ItemCache {
constructor(promise, timeout) {
this.promise = promise
this.timeout = timeout
this.cacheTime = (new Date()).getTime()
}
}
class ExpriesCache {
static cacheMap = new Map()
static isOverTime(name) {
const promise = ExpriesCache.cacheMap.get(name)
if (!promise) return true
const currentTime = (new Date()).getTime()
const overTime = (currentTime - promise.cacheTime) / 1000
if (Math.abs(overTime) > promise.timeout) {
ExpriesCache.cacheMap.delete(name)
return true
}
return false
}
static has(name) {
return !ExpriesCache.isOverTime(name)
}
static delete(name) {
return ExpriesCache.cacheMap.delete(name)
}
static get(name) {
const isDataOverTiem = ExpriesCache.isOverTime(name)
console.log(isDataOverTiem)
return isDataOverTiem ? null : ExpriesCache.cacheMap.get(name).promise
}
static set(name, promise, timeout = 600) {
const itemCache = new ItemCache(promise, timeout)
ExpriesCache.cacheMap.set(name, itemCache)
setTimeout(()=>{
console.log('删除过期数据',name)
ExpriesCache.delete(name)
}, timeout*1000)
console.log(ExpriesCache.cacheMap)
}
static getName(name,params) {
const paramsUrl = tool.paramsUrl(params)
const key = name + paramsUrl
return key
}
}
actions.forEach(item => {
let name = item.name || item.action;
api[name] = async params => {
params = params || {}
for (let i in params) {
params[i] = params[i] != 0 ? params[i] || '' : params[i];
}
let result = await api.getopenid();
let opendata = {
openid: result["openid"],
sign: result["sign"]
}
if (item.action === 'get_union_id' || item.action === 'wx_decode_data') {
opendata["session_key"] = result['session_key'];
}
let isCache = params && params.isCache
params && params.isCache && delete params.isCache
let key = ExpriesCache.getName(name,params);
let promise = ExpriesCache.get(key)
if(isCache && promise){
console.log(key)
return promise
}else{
const promise = new Promise((resolve, reject) => {
http.request({
url: item.url,
data: {
action: item.action,
t: Date.now(),
...opendata,
...params,
}
}).then(res => {
return resolve(res)
}).catch(err => {
hideLoading()
return reject(err)
})
})
isCache && ExpriesCache.set(key, promise, 10,)
return promise
}
}
})
注:该方案借鉴了其他技术大佬的方案,因大家发的都一样,不知道原作者是谁,故无备注参考文章地址
|