一、请求重试机制
核心逻辑:拦截响应失败,按策略重试
// 重试配置
const retryConfig = {
retries: 3, // 最大重试次数
retryDelay: 300, // 重试间隔(ms)
};
// 重试拦截器
axios.interceptors.response.use(null, async (error) => {
const config = error.config;
if (!config || !retryConfig.retries) return Promise.reject(error);
config.__retryCount = config.__retryCount || 0;
if (config.__retryCount >= retryConfig.retries) {
return Promise.reject(error);
}
config.__retryCount += 1;
// 指数退避策略
const delay = new Promise((resolve) => {
setTimeout(() => resolve(), retryConfig.retryDelay * config.__retryCount);
});
return delay.then(() => axios(config));
});
二、取消重复请求
核心逻辑:生成请求唯一标识,中断重复请求
const pendingMap = new Map();
// 生成请求Key
function generateReqKey(config) {
return `${config.method}_${config.url}_${JSON.stringify(config.params)}`;
}
// 请求拦截器
axios.interceptors.request.use(config => {
const key = generateReqKey(config);
if (pendingMap.has(key)) {
pendingMap.get(key).cancel('Duplicate request');
}
config.cancelToken = new axios.CancelToken(cancel => {
pendingMap.set(key, { cancel });
});
return config;
});
// 响应拦截器
axios.interceptors.response.use(response => {
const key = generateReqKey(response.config);
pendingMap.delete(key);
return response;
}, error => {
if (!axios.isCancel(error)) {
const key = generateReqKey(error.config);
pendingMap.delete(key);
}
return Promise.reject(error);
});
三、接口缓存(LRU策略)
使用lru-cache实现最近最少使用缓存
npm install lru-cache
import LRU from 'lru-cache';
const cache = new LRU({
max: 100, // 最大缓存数
maxAge: 1000 * 60 * 5, // 5分钟有效期
});
// 缓存拦截器
axios.interceptors.request.use(config => {
if (config.method !== 'get') return config;
const key = generateReqKey(config);
const cachedData = cache.get(key);
if (cachedData) {
config.adapter = () => Promise.resolve({ ...cachedData, __cached: true });
}
return config;
});
axios.interceptors.response.use(response => {
if (response.config.method === 'get' && !response.data.__cached) {
const key = generateReqKey(response.config);
cache.set(key, response.data);
}
return response;
});
四、完整集成示例
// src/utils/axios-advanced.js
import axios from 'axios';
import LRU from 'lru-cache';
const cache = new LRU({ max: 100, maxAge: 300000 });
const pendingMap = new Map();
const retryConfig = { retries: 3, retryDelay: 300 };
function generateReqKey(config) {
return `${config.method}_${config.url}_${JSON.stringify(config.params)}`;
}
// 请求拦截器
axios.interceptors.request.use(config => {
const key = generateReqKey(config);
// 取消重复请求
if (pendingMap.has(key)) {
pendingMap.get(key).cancel();
}
config.cancelToken = new axios.CancelToken(cancel => {
pendingMap.set(key, { cancel });
});
// GET请求缓存
if (config.method === 'get') {
const cachedData = cache.get(key);
if (cachedData) {
config.adapter = () => Promise.resolve({ ...cachedData, __cached: true });
}
}
return config;
});
// 响应拦截器
axios.interceptors.response.use(
response => {
const key = generateReqKey(response.config);
pendingMap.delete(key);
// 缓存有效数据
if (response.config.method === 'get' && !response.data.__cached) {
cache.set(key, response.data);
}
return response;
},
async error => {
// 请求重试
const config = error.config;
if (config && retryConfig.retries) {
config.__retryCount = config.__retryCount || 0;
if (config.__retryCount < retryConfig.retries) {
config.__retryCount += 1;
await new Promise(resolve =>
setTimeout(resolve, retryConfig.retryDelay * config.__retryCount)
);
return axios(config);
}
}
// 清理请求记录
if (error.config) {
const key = generateReqKey(error.config);
pendingMap.delete(key);
}
return Promise.reject(error);
}
);
export default axios;
五、性能优化建议
- 缓存策略:对高频静态数据(如城市列表)设置更长缓存时间
cache.set(key, data, 1000 * 60 * 60); // 1小时缓存 - 重试条件:仅对特定状态码重试
if ([502, 503, 504].includes(error.response?.status)) { // 执行重试逻辑 } - LRU监控:实时查看缓存状态
console.log(cache.size); // 当前缓存数量 console.log(cache.keys()); // 查看所有缓存键
通过该方案,可提升应用在弱网环境的稳定性,减少冗余请求,显著改善用户体验。
&spm=1001.2101.3001.5002&articleId=158384081&d=1&t=3&u=6569c54b366e43f499a6b1665000e025)
2869

被折叠的 条评论
为什么被折叠?



