前端实现超时请求重传

在网络不稳定的场景下,超时请求重传 是提升应用健壮性的关键策略。以下是前端实现请求超时重试的完整方案,涵盖 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. 优化策略:指数退避 + 智能提示提升用户体验
相关推荐
Rhys..19 分钟前
如何禁止chrome自动更新
前端·chrome
巴巴_羊26 分钟前
AJAX 使用 和 HTTP
前端·http·ajax
刺客-Andy33 分钟前
React 第四十一节Router 中 useActionData 使用方法案例以及注意事项
前端·react.js·前端框架
岁岁岁平安37 分钟前
Vue3学习(组合式API——reactive()和ref()函数详解)
前端·javascript·vue.js·学习·vue3·reactive·ref
肠胃炎39 分钟前
React事件机制
前端·javascript·react.js
CUIYD_19891 小时前
javascript —— ! 和 !! 的区别与作用
前端·javascript·vue.js
帅帅哥的兜兜2 小时前
next.js实现项目搭建
前端·react.js·next.js
筱歌儿2 小时前
css 左右布局
前端·css
GISer_Jing3 小时前
编译原理AST&以Babel为例进行解读、Webpack中自定义loader与plugin
前端·webpack·node.js
GISer_Jing3 小时前
Webpack中Compiler详解以及自定义loader和plugin详解
前端·webpack·node.js