ReactJS中fetch请求返回408/503错误时如何实现自动重试
实现思路
直接在原有请求封装的基础上新增重试逻辑,核心改动点如下:
- 新增重试配置项,支持自定义最大重试次数、重试间隔,默认配置为最大重试3次、每次间隔1000ms,兼容原有调用方式
- 捕获请求过程中抛出的状态码错误,仅当状态码为408、503且仍有剩余重试次数时,等待指定间隔后重新发起请求
- 超过最大重试次数、或遇到其他状态码错误/网络错误时,直接抛出异常走原有错误处理逻辑
- 新增等待工具函数实现重试间隔,避免请求瞬间高频发起冲击服务端
修改后完整代码
export class ResponseError extends Error { public response: Response; constructor(response: Response) { super(response.statusText); this.response = response; } } function parseJSON(response: Response) { if (response.status === 204 || response.status === 205) { return null; } return response.json(); } function checkStatus(response: Response) { if (response.status >= 200 && response.status < 300) { return response; } const error = new ResponseError(response); error.response = response; throw error; } // 重试配置类型定义 interface RetryOptions { maxRetries?: number; retryDelay?: number; } // 等待工具函数 const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); // 判断是否为需要重试的状态码 function isRetryableError(error: unknown): error is ResponseError { if (error instanceof ResponseError) { const status = error.response.status; return status === 408 || status === 503; } return false; } export async function request( url: string, options?: RequestInit, retryOptions: RetryOptions = {} ): Promise<{} | { err: ResponseError }> { // 合并默认重试配置 const { maxRetries = 3, retryDelay = 1000 } = retryOptions; let retries = 0; while (true) { try { const fetchResponse = await fetch(url, options); const response = checkStatus(fetchResponse); return parseJSON(response); } catch (err) { // 不满足重试条件 或 重试次数耗尽,直接抛出错误 if (!isRetryableError(err) || retries >= maxRetries) { throw err; } // 等待指定间隔后重试 await wait(retryDelay); retries++; } } }
使用说明
- 原有调用方式完全兼容,不需要修改旧代码,默认会对408、503状态自动重试3次
- 特殊接口可自定义重试规则,示例:
// 该接口最多重试1次,每次间隔500ms request('/api/data', { method: 'GET' }, { maxRetries: 1, retryDelay: 500 }) // 该接口关闭自动重试 request('/api/submit', { method: 'POST' }, { maxRetries: 0 })
- 注意:POST/PUT/DELETE等写操作接口开启重试前,请确认接口实现了幂等性,避免重复提交产生业务脏数据
- 如果需要更友好的重试策略,可将固定间隔修改为指数退避逻辑,即每次重试间隔按倍数拉长,降低服务端压力
内容的提问来源于stack exchange,提问作者Tambua Rex
相关产品推荐
相关产品推荐

