前端实现超时请求重传

在网络不稳定的场景下,超时请求重传 是提升应用健壮性的关键策略。以下是前端实现请求超时重试的完整方案,涵盖 AxiosFetch API 两种主流方式,帮你轻松应对网络波动!


核心实现方案

1. 基于 Axios 实现(推荐)

Axios 提供了拦截器(interceptors)和配置项,非常适合实现超时重传。

完整代码示例

typescript 复制代码
import axios, { AxiosRequestConfig, AxiosError } from 'axios';

// 重试配置
const RETRY_COUNT = 3; // 最大重试次数
const RETRY_DELAY = 1000; // 重试延迟(ms)
const TIMEOUT = 5000; // 单次请求超时时间(ms)

// 创建 Axios 实例
const http = axios.create({ timeout: TIMEOUT });

// 请求拦截器:记录重试次数
http.interceptors.request.use((config: any) => {
  config.__retryCount = config.__retryCount || 0;
  return config;
});

// 响应拦截器:错误处理与重试
http.interceptors.response.use(null, async (error: AxiosError) => {
  const config = error.config;

  // 如果不是超时错误或达到重试上限,直接拒绝
  if (
    error.code !== 'ECONNABORTED' || 
    config.__retryCount >= RETRY_COUNT
  ) {
    return Promise.reject(error);
  }

  // 增加重试计数
  config.__retryCount += 1;

  // 延迟重试
  await new Promise(resolve => 
    setTimeout(resolve, RETRY_DELAY)
  );

  return http(config);
});

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

关键点说明

  1. 错误类型判断 :只重试超时错误(ECONNABORTED
  2. 重试控制 :通过 __retryCount 记录已重试次数
  3. 延迟重试:避免立即重试导致服务器压力骤增

2. 基于 Fetch API 实现

Fetch API 需要手动封装重试逻辑,适合原生场景。

完整代码示例

typescript 复制代码
const fetchWithRetry = async (
  url: string,
  options: RequestInit = {},
  retries: number = 3,
  delay: number = 1000
): Promise<Response> => {
  try {
    // 添加超时控制
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 5000);
    
    const response = await fetch(url, {
      ...options,
      signal: controller.signal
    });
    
    clearTimeout(timeoutId);
    
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    return response;
  } catch (error) {
    if (retries <= 0) throw error;
    await new Promise(resolve => setTimeout(resolve, delay));
    return fetchWithRetry(url, options, retries - 1, delay);
  }
};

// 使用示例
fetchWithRetry('/api/data')
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error('最终失败:', err));

关键点说明

  1. 超时控制 :通过 AbortController 实现
  2. 递归重试:通过递归调用实现次数控制
  3. 错误边界:区分网络错误和业务错误(HTTP状态码)

高级优化策略

1. 指数退避算法

重试间隔随时间指数增长,避免雪崩效应:

arduino 复制代码
const delay = Math.pow(2, retries) * 1000; // 2^n秒

2. 关键请求标记

对支付等关键请求启用重试,对普通查询请求禁用:

arduino 复制代码
if (config.isCritical) {
  // 执行重试逻辑
}

3. 用户提示优化

  • 首次失败显示"正在重试..."
  • 最终失败显示"网络不稳定,请手动重试"

各方案对比

方案 优点 缺点 适用场景
Axios 拦截器机制完善 需要封装 已有Axios的项目
Fetch 浏览器原生支持 手动实现复杂 追求轻量的项目
React Query 内置重试机制 需要引入额外库 React生态

总结

  1. Axios 方案:通过拦截器优雅实现,适合大多数项目
  2. Fetch 方案:更底层控制,适合特殊需求场景
  3. 优化策略:指数退避 + 智能提示提升用户体验
相关推荐
倔强青铜三28 分钟前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试
excel1 小时前
Node.js 断言与测试框架示例对比
前端
天蓝色的鱼鱼3 小时前
前端开发者的组件设计之痛:为什么我的组件总是难以维护?
前端·react.js
codingandsleeping3 小时前
使用orval自动拉取swagger文档并生成ts接口
前端·javascript
石金龙4 小时前
[译] Composition in CSS
前端·css
白水清风4 小时前
微前端学习记录(qiankun、wujie、micro-app)
前端·javascript·前端工程化
Ticnix4 小时前
函数封装实现Echarts多表渲染/叠加渲染
前端·echarts
用户22152044278004 小时前
new、原型和原型链浅析
前端·javascript
阿星做前端4 小时前
coze源码解读: space develop 页面
前端·javascript
叫我小窝吧4 小时前
Promise 的使用
前端·javascript