闽公网安备 35020302035485号
| 特性 | cookie | localStorage | sessionStorage | indexDB |
|---|---|---|---|---|
| 数据生命周期 | 服务器或者客户端都可以设置、有过期时间 | 一直存在 | 关闭页面就清空 | 一直存在 |
| 数据储存大小 | 4KB | 5MB | 5MB |
动态,很大 大于250MB |
| 与服务器通信 | 每次都带在header中 | 不带 | 不带 | 不带 |
| 兼容性 | 都支持 | 都支持 | 都支持 | IE不支持,其他主流都支持 |


劫持所有接口,判断接口状态与缓存标识。从而进行更新数据、获取数据、缓存策略三种操作。
通过配置白名单来控制接口存与取:
axios.interceptors.response.use(
async (resp) => {
const { config } = resp
const { url } = config
// 是否有缓存tag,用于更新CDN数据。目前是定时服务在跑,访问页面带上tag
if (this.hasCdnTag() && this.isWhiteApi(url)) {
this.updateCDN(config, resp)
}
return resp;
},
async (err) => {
const { config } = err
const { url } = config
// 是否命中缓存策略
if (this.isWhiteApi(url) && this.useCache()) {
return this.fetchCDN(config).then(res => {
pushLog(`cdn缓存数据已命中,请处理`, SentryTypeEnum.error)
return res
}).catch(()=>{
pushLog(`cdn缓存数据未同步,请处理`, SentryTypeEnum.error)
})
}
}
);
/*
* 缓存策略
*/
useCache = () => {
if (this.expiresStamp > +new Date()) {
const d = new Date(this.expiresStamp)
console.warn(`
---------------------------------------
---------------------------------------
启用缓存中
关闭时间:${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}
---------------------------------------
---------------------------------------
`)
return true
}
this.errorCount += 1
localStorage.setItem(CACHE_ERROR_COUNT_KEY, `${this.errorCount}`)
if (this.errorCount > this.maxCount) {
this.expiresStamp = +new Date() + this.expiresSeconds * 1000
this.errorCount = 0
localStorage.setItem(CACHE_EXPIRES_KEY, `${this.expiresStamp}`)
localStorage.removeItem(CACHE_ERROR_COUNT_KEY)
return true
}
return false
}
/**
* 堆代码 duidaima.com
* 生成接口唯一键值
*/
generateCacheKey = (config) => {
// 请求方式,参数,请求地址,
const { method, url, data, params } = config;
let rawData = ''
if (method === 'get') {
rawData = params
}
if (method === 'post') {
rawData = JSON.parse(data)
}
// 返回拼接key
return `${encodeURIComponent([method, url, stringify(rawData)].join('_'))}.json`;
};
更新数据
/**
* 更新cdn缓存数据
*/
updateCDN = (config, data) => {
const fileName = this.generateCacheKey(config)
const cdnUrl = `${this.prefix}/${fileName}`
axios.post(`${this.nodeDomain}/cdn/update`, {
cdnUrl,
data
})
}
import schedule from 'node-schedule';
const scheduleJob = {};
export const xxxJob = (ctx) => {
const { xxx } = ctx.config;
ctx.logger.info(xxx, 'xxx');
const { key, url, rule } = xxx;
if (scheduleJob[key]) {
scheduleJob[key].cancel();
}
scheduleJob[key] = schedule.scheduleJob(rule, async () => {
ctx.logger.info(url, new Date());
await browserIndex(ctx, url);
});
};
export const browserIndex = async (ctx, domain) => {
ctx.logger.info('browser --start', domain);
if (!domain) {
ctx.logger.error('domain为空');
return false;
}
const browser = await puppeteer.launch({
args: [
'--use-gl=egl',
'--disable-gpu',
'--no-sandbox',
'--disable-setuid-sandbox',
],
executablePath: process.env.CHROMIUM_PATH,
headless: true,
timeout: 0,
});
const page = await browser.newPage();
await page.goto(`${domain}?${URL_CACHE_KEY}`);
await sleep(10000);
// 访问首页所有查询接口
const list = await page.$$('.po-tabs__item');
if (list?.length) {
for (let i = 0; i < list.length; i++) {
await list[i].click();
}
}
await browser.close();
ctx.logger.info('browser --finish', domain);
return true;
};

axios.interceptors.response.use(
async (resp) => {
const { config } = resp
const { url } = config
// 是否有缓存tag,用于更新CDN数据。目前是定时服务在跑,访问页面带上tag
if (this.hasCdnTag() && this.isWhiteApi(url)) {
this.updateCDN(config, resp)
}
if(this.isIndexDBWhiteApi(url)){
this.updateIndexDB(config, resp)
}
return resp;
},
async (err) => {
const { config } = err
const { url } = config
// 是否命中缓存策略
if (this.isWhiteApi(url) && this.useCache()) {
return this.fetchCDN(config).then(res => {
pushLog(`cdn缓存数据已命中,请处理`, SentryTypeEnum.error)
return res
}).catch(()=>{
pushLog(`cdn缓存数据未同步,请处理`, SentryTypeEnum.error)
if(this.isIndexDBWhiteApi(url)){
return this.fetchIndexDB(config).then(res => {
pushLog(`IndexDB缓存数据已命中,请处理`, SentryTypeEnum.error)
return res
}).catch(()=>{
pushLog(`IndexDB缓存数据未同步,请处理`, SentryTypeEnum.error)
})
}
})
}
}
);