前端实现超时请求重传

在网络不稳定的场景下,超时请求重传 是提升应用健壮性的关键策略。以下是前端实现请求超时重试的完整方案,涵盖 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. 优化策略:指数退避 + 智能提示提升用户体验
相关推荐
夏鹏今天学习了吗3 小时前
【性能优化】前端高性能优化策略
前端·性能优化
ShineWinsu6 小时前
对于数据结构:堆的超详细保姆级解析——下(堆排序以及TOP-K问题)
c语言·数据结构·c++·算法·面试·二叉树·
weixin_427771616 小时前
css font-size 的妙用
前端·css
_Power_Y6 小时前
计算机网络面试题
面试
凤凰战士芭比Q6 小时前
web中间件——Nginx
前端·nginx·中间件
一 乐7 小时前
点餐|智能点餐系统|基于java+ Springboot的动端的点餐系统小程序(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·小程序·论文
视图猿人7 小时前
RxJS基本使用及在next.js中使用的例子
开发语言·javascript
火山上的企鹅7 小时前
Qt C++ 软件开发工程师面试题
c++·qt·面试
bitbitDown8 小时前
从零打造一个 Vite 脚手架工具:比你想象的简单多了
前端·javascript·面试
沐怡旸8 小时前
【穿越Effective C++】条款16:成对使用new和delete时要采用相同形式——内存管理的精确匹配原则
c++·面试