Fetch API 通过 AbortController 实现精准超时控制,需创建 controller、传 signal、setTimeout 调 abort(),并清理定时器、识别 AbortError、每次新建 controller;封装为 fetchWithTimeout 函数可复用,优于 Promise.race 等伪中断方案。

Fetch API 本身不提供 timeout 参数,但可以通过 AbortController 配合 AbortSignal 实现精准的超时控制与主动中断。关键不是“等它超时”,而是“到点就中止”,并正确捕获和清理。
用 AbortController 主动中止请求
这是现代浏览器推荐的标准方式,兼容性好(Chrome 66+、Firefox 57+、Safari 12.1+),语义清晰,且能真正终止底层网络连接。
- 创建
AbortController实例,取出它的signal - 将
signal作为options.signal传给fetch() - 用
setTimeout在指定毫秒后调用controller.abort() -
fetch接收到 abort 信号后会立即抛出name === 'AbortError'的错误
必须注意的三个细节
光写上 abort() 不够,实际使用中容易漏掉关键处理:
-
定时器要手动清理:请求成功或失败后,都需调用
clearTimeout(timeoutId),避免内存泄漏或误触发 -
AbortError 要显式识别:不能只靠
catch一并处理,需判断err.name === 'AbortError'来区分是超时还是网络/服务端错误 -
signal 可复用但不可重用:一个
signal只能触发一次 abort;如需多次请求,每次都要新建AbortController
封装成可复用的 fetchWithTimeout 函数
把逻辑收拢成函数,方便在项目中统一管理超时行为:
立即学习“Java免费学习笔记(深入)”;
function fetchWithTimeout(url, options = {}, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
return fetch(url, {
...options,
signal: controller.signal
}).finally(() => clearTimeout(timeoutId));
}
调用时可直接配合 async/await 使用,并单独处理超时分支:
try {
const res = await fetchWithTimeout('/api/data', {}, 3000);
const data = await res.json();
} catch (err) {
if (err.name === 'AbortError') {
throw new Error('请求超时,请稍后重试');
}
throw err;
}
不推荐的替代方案:Promise.race
有人用 Promise.race([fetch(), timeoutPromise]) 模拟超时,但它只是“放弃等待”,fetch 请求仍在后台运行,可能浪费带宽、触发重复副作用,且无法真正中断连接。AbortController 是唯一能实现物理中止的方案。


















