处理 Fetch 异常需分三类:网络层失败(如 TypeError)可重试;HTTP 状态异常中 5xx 可重试、4xx 一般不重试;响应解析失败应主动 throw。超时须用 AbortController 配合 signal,检查 AbortError 统一处理。

处理 Fetch 请求的网络异常和超时,核心在于主动识别并分类错误类型,而不是依赖 fetch 自动抛错——因为 fetch 只在网络彻底失败(如断网、DNS 解析失败、CORS 拒绝)或被中止时才进 catch;而 404、500 等 HTTP 状态码默认不触发拒绝,必须手动判断。
区分三类常见异常并分别应对
实际开发中,请求失败大致分三类,每类需不同处理逻辑:
-
网络层失败:例如
TypeError: Failed to fetch、AbortError、DNS 错误。这类属于临时性问题,适合立即重试。 -
HTTP 状态异常:响应已收到但
res.ok === false。需进一步检查res.status:
• 500–599(服务端故障)可重试;
• 400–499(除 408 请求超时、429 频率限制)一般不重试,直接报错或提示用户修正输入。 -
响应体解析失败:比如
await res.json()报SyntaxError(非标准 JSON)。应主动throw,使其进入catch分支,统一走重试或降级流程。
用 AbortController 实现可控超时
fetch 本身没有超时机制,靠 Promise.race 包裹只是“假装取消”,底层请求仍在运行,可能造成资源堆积。正确做法是结合 AbortController:
- 创建
controller = new AbortController(),把controller.signal传入 fetch 的options; - 用
setTimeout(() => controller.abort(), timeoutMs)设置硬性截止时间; - 在
catch中检查err.name === 'AbortError',即可确认是超时导致,并纳入可重试分支。
封装时用 if-else 明确控制流程
避免无限递归或死循环,每次重试前用计数器做显式判断:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
- 当前尝试次数
- 已是最后一次尝试 → 不再等待,直接
throw err,交由上层统一兜底(如展示错误提示); - 响应成功(
res.ok === true)→ 立即return await res.json()或其他解析结果,退出整个重试流程。
基础封装示例(含超时与状态码判断)
以下是一个轻量但完整的结构示意,重点看条件分支如何串联:
async function fetchWithTimeout(url, options = {}, timeout = 5000, maxRetries = 2) {
for (let i = 0; i <= maxRetries; i++) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const res = await fetch(url, { ...options, signal: controller.signal });
clearTimeout(timeoutId);
if (!res.ok) {
if (res.status >= 500 && res.status < 600) {
if (i < maxRetries) continue;
} else throw new Error(`HTTP ${res.status}`);
}
return await res.json();
} catch (err) {
if (err.name === 'AbortError' || err.name === 'TypeError') {
if (i < maxRetries) continue;
}
throw err;
}
}
throw new Error('Request failed after retries');
}

















