超时取消HTTP请求的方法
阅读 22
在系统监控与心跳探活等场景中,我们常常会对某些设备或API接口发起HTTP请求,如果超时就算失败,因为一直等待下去没有太大的意义。
那么,这就会涉及到一个问题:如何将发起的Ajax请求设置为超时取消呢?
XHR(老式汽车)
XHR 全称是 XMLHttpRequest,它是浏览器最早提供的、用来实现 Ajax 思想的内置函数。可以说,它是 Ajax 技术的“鼻祖”。
它自带 xhr.timeout 和 xhr.abort(),但基于回调函数的 API 极其冗长,且无法优雅地配合现代的 async/await 异步流。
随着Fetch方法的出现,XHR已经慢慢被淘汰了。
Fetch(新式高铁)
但是,在Fetch早期,我们却无法使用它来实现真正的底层网络取消。
开发者常用如下写法来模拟超时:
Promise.race([fetch(), timeoutPromise()])但这种写法只能让代码提前抛出异常,底层的 TCP 连接和 HTTP 请求在后台依然会继续传输,无法省去带宽消耗,也无法减轻服务端压力。
为了解决这个问题,人们引入了AbortController ,用它结合setTimeout来实现要求:
const controller = new AbortController()
const timeout = setTimeout(() => {
controller.abort()
}, 5000)
try {
const response = await fetch(url, {
method: 'GET',
signal: controller.signal
})
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
} finally {
clearTimeout(timeout)
}这种方式虽然能满足上面的要求,但是实现较繁琐(需维护 controller 与 timer )。
在纯超时场景下(无需手动提前取消请求),AbortSignal.timeout()方法可以更简洁地实现该要求:
try {
const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
const result = await res.json();
// …
}需要注意的是,后者推出的时间更晚,需要考虑当前环境的兼容性问题。
另外,前者抛出的异常是AbortError,AbortSignal.timeout()抛出的是TimeoutError。
参考
最后编辑于: 2026-08-26