第六阶段:Vue生态高级整合与优化(第100天)Vue与Axios进阶:请求重试+取消重复请求+接口缓存策略(lru-cache)

一、请求重试机制

核心逻辑:拦截响应失败,按策略重试

// 重试配置
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;


五、性能优化建议

  1. 缓存策略:对高频静态数据(如城市列表)设置更长缓存时间
    cache.set(key, data, 1000 * 60 * 60); // 1小时缓存
    

  2. 重试条件:仅对特定状态码重试
    if ([502, 503, 504].includes(error.response?.status)) {
      // 执行重试逻辑
    }
    

  3. LRU监控:实时查看缓存状态
    console.log(cache.size); // 当前缓存数量
    console.log(cache.keys()); // 查看所有缓存键
    

通过该方案,可提升应用在弱网环境的稳定性,减少冗余请求,显著改善用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值