特性 | 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) }) } }) } } );