Axios请求超时重发机制

发布于:2025-06-07 ⋅ 阅读:(17) ⋅ 点赞:(0)

Axios 超时重新请求实现方案

在 Axios 中实现超时重新请求可以通过以下几种方式:

1. 使用拦截器实现自动重试

import axios from 'axios';

// 创建axios实例
const instance = axios.create();

// 设置超时时间
instance.defaults.timeout = 5000;

// 最大重试次数
const MAX_RETRY = 3;

// 添加请求拦截器
instance.interceptors.response.use(undefined, (error) => {
  const config = error.config;
  
  // 如果配置不存在或未设置重试选项,则拒绝
  if (!config || !config.retry) return Promise.reject(error);
  
  // 设置重试次数变量
  config.__retryCount = config.__retryCount || 0;
  
  // 检查是否已达到最大重试次数
  if (config.__retryCount >= config.retry) {
    return Promise.reject(error);
  }
  
  // 增加重试计数器
  config.__retryCount += 1;
  
  // 创建新的Promise来处理指数退避
  const backoff = new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, config.retryDelay || 1000);
  });
  
  // 返回Promise,在退避时间后重试请求
  return backoff.then(() => instance(config));
});

// 使用示例
instance.get('/api/data', {
  retry: MAX_RETRY, // 重试次数
  retryDelay: 1000 // 重试延迟时间(毫秒)
}).then(response => {
  console.log(response.data);
}).catch(error => {
  console.error('请求失败:', error);
});

2. 封装请求函数实现重试

function requestWithRetry(url, options = {}, retryCount = 3) {
  return new Promise((resolve, reject) => {
    const attempt = (currentRetry) => {
      axios({
        url,
        ...options,
        timeout: options.timeout || 5000
      })
        .then(resolve)
        .catch((error) => {
          if (currentRetry <= 0 || !isRetryable(error)) {
            return reject(error);
          }
          
          console.log(`请求失败,剩余重试次数: ${currentRetry - 1}`);
          
          // 指数退避
          const delay = Math.pow(2, retryCount - currentRetry) * 1000;
          
          setTimeout(() => {
            attempt(currentRetry - 1);
          }, delay);
        });
    };
    
    attempt(retryCount);
  });
}

// 判断错误是否可重试
function isRetryable(error) {
  return (
    error.code === 'ECONNABORTED' || // 超时
    !error.response || // 无响应(网络错误)
    error.response.status >= 500 // 服务器错误
  );
}

// 使用示例
requestWithRetry('/api/data', { method: 'get' }, 3)
  .then(response => console.log(response.data))
  .catch(error => console.error('最终失败:', error));

3. 使用第三方库

也可以使用专门处理重试的库,如 axios-retry:

import axios from 'axios';
import axiosRetry from 'axios-retry';

// 配置axios-retry
axiosRetry(axios, {
  retries: 3, // 重试次数
  retryDelay: (retryCount) => {
    return retryCount * 1000; // 重试延迟
  },
  retryCondition: (error) => {
    // 只在超时或5xx错误时重试
    return axiosRetry.isNetworkOrIdempotentRequestError(error) || 
      error.code === 'ECONNABORTED';
  }
});

// 正常使用axios
axios.get('/api/data', { timeout: 5000 })
  .then(response => console.log(response.data))
  .catch(error => console.error('请求失败:', error));

注意事项

  1. 幂等性:确保请求是幂等的(GET、HEAD、OPTIONS、PUT、DELETE等),POST请求重试可能导致重复操作
  2. 退避策略:建议使用指数退避策略,避免同时重试大量请求
  3. 用户体验:对于前端应用,应考虑用户等待时间,不宜设置过多重试次数
  4. 取消请求:如果用户导航离开页面,应取消未完成的请求

以上方案可以根据实际需求进行调整和组合使用。


网站公告

今日签到

点亮在社区的每一天
去签到