fetch本身不支持直接设置超时,但可通过AbortController配合Promise.race实现:创建controller并传入signal,超时调用abort()触发AbortError;封装fetchWithTimeout函数复用逻辑;或用Promise.race与延时reject的Promise竞速以明确区分超时错误。

fetch 本身不支持直接设置超时时间,但可以通过 AbortController 配合 Promise.race 实现请求超时控制。
用 AbortController 主动中断请求
现代浏览器支持 AbortController API,它能向 fetch 发送中止信号。关键在于:在超时前调用 controller.abort(),fetch 就会抛出 AbortError 异常。
- 创建
const controller = new AbortController() - 把
signal: controller.signal传入 fetch 的 options - 用
setTimeout(() => controller.abort(), timeoutMs)设置超时触发
封装一个带超时的 fetch 函数
把超时逻辑封装起来更易复用,避免每次手动写重复代码:
function fetchWithTimeout(url, options = {}, timeout = 5000) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
return fetch(url, {
...options,
signal: controller.signal
}).finally(() => clearTimeout(id));
}
使用时直接调用即可:fetchWithTimeout('/api/data', { method: 'POST' }, 8000),8 秒没响应就自动中断。
配合 Promise.race 处理更明确的超时错误
如果希望区分“网络失败”和“超时”,可用 Promise.race 让 fetch 和一个延时 reject 的 Promise 竞速:
- 定义一个超时 Promise:
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Request timed out')), 5000)) - 用
Promise.race([fetch(...), timeoutPromise])包裹请求 - 捕获错误时可判断是否为超时(例如检查 error.message 是否包含 'timed out')
注意兼容性和实际限制
AbortController 在 IE 中完全不支持,如需兼容旧版浏览器,得用 axios 或手写 XMLHttpRequest + timeout 属性。另外要注意:fetch 超时后,底层连接可能仍在后台传输数据,Abort 只是让 JS 不再等待响应,并不强制终止 TCP 连接。


















