注:本篇博客借鉴了https://segmentfault.com/a/1190000022758406
在此基础上,又根据我的项目https://blog.csdn.net/fmtzy1991/article/details/109065167
做了部分改变;
- 目录结构
- 用到了apiBefor,cryptoHelper,storage三个文件
- apiBefor 是对接口的再封装
import axios from 'axios'; import storage from './storage'; import cryptoHelper from './cryptoHelper'; const root = process.env.API_ROOT; if (process.env.NODE_ENV === "development") { axios.defaults.baseURL = root }else { axios.defaults.baseURL = root } axios.defaults.headers.post['Content-Type']='application/x-www-form-urlencoded'; const CANCELTTYPE = { CACHE: 1, REPEAT: 2, }; const pendingRequests = []; const http = axios.create(); http.interceptors.request.use((config) => { /** * 为每一次请求生成一个cancleToken */ const source = axios.CancelToken.source(); config.cancelToken = source.token; /** * 缓存命中判断 * 成功则取消当次请求 */ //处理FormData生成详细key存储数据 let objData = {}; for (let entry of config.data.entries()){ objData[entry[0]] = entry[1]; } //尝试获取缓存数据 const data = storage.get(cryptoHelper.encrypt( config.url + JSON.stringify(objData) + (config.method || '') )); if (data && (Date.now() <= data.exppries)) { console.log(`接口:${config.url} 参数:${JSON.stringify(objData)}缓存命中 -- ${Date.now()} -- ${data.exppries}`); source.cancel(JSON.stringify({ type: CANCELTTYPE.CACHE, data: data.data, })); } return config; }); http.interceptors.response.use((res) => { if (res.data) { const dataParse = res.data; //添加缓存时间 if (!dataParse.cacheTime) { dataParse.cacheTime = 1000 * 60 * 5; } //处理FormData生成详细key存储数据 let objData = {}; for (let entry of res.config.data.entries()){ objData[entry[0]] = entry[1]; } //设置缓存数据 storage.set(cryptoHelper.encrypt(res.config.url + JSON.stringify(objData) + (res.config.method || '')), { data: res.data, exppries: Date.now() + dataParse.cacheTime, }); console.log(`接口:${res.config.url} 参数:${JSON.stringify(objData)} 设置缓存,缓存时间: ${dataParse.cacheTime}`); return res.data; } else if(res.data == ''){ return res.data; }else { return Promise.reject('接口报错了!'); } }); /** * 封装 get、post 请求 * 集成接口缓存过期机制 * 缓存过期将重新请求获取最新数据,并更新缓存 * 数据存储在localstorage * { * cache: true * cacheTime: 1000 * 60 * 3 -- 默认缓存3分钟 * } */ const httpHelper = { get(url, params) { return new Promise((resolve, reject) => { http.get(url, params).then(async (res) => { resolve(res); }).catch(error => { if (axios.isCancel(error)) { const cancle = JSON.parse(error.message); if (cancle.type === CANCELTTYPE.REPEAT) { return resolve([]); } else { return resolve(cancle.data); } } else { return reject(error); } }); }); }, post(url, params) { return new Promise((resolve, reject) => { http.post(url, params).then(async (res) => { resolve(res); }).catch(error => { if (axios.isCancel(error)) { const cancle = JSON.parse(error.message); if (cancle.type === CANCELTTYPE.REPEAT) { return resolve(null); } else { return resolve(cancle.data); } } else { return reject(error); } }); }); }, }; export default httpHelper;
- storage是数据存储
const Storage = { get(key) { if (!key) { return; } const text = localStorage.getItem(key); if (text) { return JSON.parse(text); } else { localStorage.removeItem(key); return null; } }, set(key, data) { if (!key) { return; } localStorage.setItem(key, JSON.stringify(data)); }, remove(key) { if (!key) { return; } localStorage.removeItem(key); } } export default Storage;
- cryptoHelper生成加密串
import cryptoJs from 'crypto-js'; const CryptoHelper = { constructor(key) { /** * 如需秘钥,可以在实例化时传入 */ this.key = key; }, /** * 加密 * @param word */ encrypt(word) { if (!word) { return ''; } const encrypted = cryptoJs.MD5(word); return encrypted.toString(); } } export default CryptoHelper;
- 注意地方:因为我之前是用fromdata方式传参,所以在生成存储变量时要做一下数据处理,将参数转化为字符串,否则在调取缓存数据时不能精准调取;然后返回数据量过多的接口也不建议使用缓存;