前端实现超时请求重传

在网络不稳定的场景下,超时请求重传 是提升应用健壮性的关键策略。以下是前端实现请求超时重试的完整方案,涵盖 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. 优化策略:指数退避 + 智能提示提升用户体验
相关推荐
键盘不能没有CV键3 小时前
【图片处理】✈️HTML转图片字体异常处理
前端·javascript·html
yantuguiguziPGJ4 小时前
WPF 联合 Web 开发调试流程梳理(基于 Microsoft.Web.WebView2)
前端·microsoft·wpf
大飞记Python4 小时前
部门管理|“编辑部门”功能实现(Django5零基础Web平台)
前端·数据库·python·django
tsumikistep5 小时前
【前端】前端运行环境的结构
前端
你的人类朋友5 小时前
【Node】认识multer库
前端·javascript·后端
Aitter5 小时前
PDF和Word文件转换为Markdown的技术实现
前端·ai编程
mapbar_front6 小时前
面试问题—上家公司的离职原因
前端·面试
昔人'7 小时前
css使用 :where() 来简化大型 CSS 选择器列表
前端·css
昔人'7 小时前
css `dorp-shadow`
前端·css
流***陌7 小时前
扭蛋机 Roll 福利房小程序前端功能设计:融合趣味互动与福利适配
前端·小程序