Axios请求超时重发机制

Axios 超时重新请求实现方案

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

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

javascript 复制代码
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. 封装请求函数实现重试

javascript 复制代码
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:

javascript 复制代码
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. 取消请求:如果用户导航离开页面,应取消未完成的请求

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

相关推荐
一灯架构6 小时前
90%的人答错!一文带你彻底搞懂ArrayList
java·后端
Y4090017 小时前
【多线程】线程安全(1)
java·开发语言·jvm
布局呆星8 小时前
SpringBoot 基础入门
java·spring boot·spring
风吹迎面入袖凉8 小时前
【Redis】Redisson的可重入锁原理
java·redis
w6100104668 小时前
cka-2026-ConfigMap
java·linux·cka·configmap
语戚9 小时前
力扣 968. 监控二叉树 —— 贪心 & 树形 DP 双解法递归 + 非递归全解(Java 实现)
java·算法·leetcode·贪心算法·动态规划·力扣·
quxuexi9 小时前
网络通信安全与可靠传输:从加密到认证,从状态码到可靠传输
java·安全·web
hrhcode10 小时前
【java工程师快速上手go】二.Go进阶特性
java·golang·go
小碗羊肉11 小时前
【从零开始学Java | 第三十一篇下】Stream流
java·开发语言