在 async 函数中处理 fetch 超时需主动介入,因 fetch 无内置 timeout;推荐用 abortcontroller 配合 signal 实现标准可取消超时,或用 promise.race() 手动封装超时逻辑,并在 catch 中通过 err.name === 'aborterror' 或 message 包含 'timeout' 判断超时,调用层仍需兜底捕获错误。

在 async 函数中用 try-catch 处理网络超时,不能只靠捕获 Promise rejection —— 因为 fetch 本身不因超时自动 reject,它可能一直 pending,直到浏览器强制终止并抛出 TypeError: Failed to fetch(如断网、DNS失败),但标准 fetch 没有内置超时机制。真正的超时控制必须主动介入。
手动添加请求超时逻辑
fetch 不支持 timeout 参数,需用 Promsie.race() 包裹请求与一个定时 reject 的 Promise:
- 创建一个在指定毫秒后
reject(new Error('Request timeout'))的 Promise - 用
Promise.race([fetch(...), timeoutPromise])竞速,任一先完成即返回结果或错误 - await 这个 race 结果,再进 try-catch —— 超时会作为普通 Error 被捕获
区分超时和其他网络异常
捕获到错误后,需判断是否为超时,以便差异化处理:
- 检查
err.name === 'AbortError'(配合AbortController更规范) - 或匹配
err.message.includes('timeout')(手动 race 方式) - 对超时可触发重试;对
TypeError: Failed to fetch可提示“网络异常”
推荐结合 AbortController 使用
比手动 race 更标准、可取消、兼容性好:
- 创建
const controller = new AbortController() - fetch 时传入
{ signal: controller.signal } - 启动定时器:
setTimeout(() => controller.abort(), 8000) - catch 中识别
err.name === 'AbortError'即为超时
调用层仍需兜底
即使内部做了超时控制,async 函数返回的 Promise 仍可能被 reject:
- 按钮点击、useEffect 等调用处,建议保留 .catch 或外层 try-catch
- 避免未捕获的 rejection 触发
unhandledrejection事件 - 尤其在用户关键操作(如提交表单)中,应明确展示超时反馈而非静默失败











