AbortController 是浏览器提供的用于中止异步操作的信号机制,必须在需主动取消 fetch 请求(如页面切换、搜索防抖、组件卸载)时使用,否则请求无法真正终止,易导致资源浪费和竞态问题。

AbortController 是什么,什么时候必须用它
AbortController 不是浏览器的“高级功能”,而是现代 fetch 的基础配套机制。如果你在发请求后需要手动中止(比如用户切换页面、输入框快速连打、表单提交前取消上一次请求),又不想靠“设个 flag 然后 if 判断”这种不可靠方式,就必须用它。不用 AbortController,fetch 请求一旦发出就无法真正终止 —— 它会继续走完网络层,只是 JS 不再监听响应,造成资源浪费和潜在竞态问题。
怎么正确创建并传入 signal 给 fetch
关键不是“加了 signal 就能取消”,而是 signal 必须在 fetch 调用前已存在,且不能复用:
fetch 调用前已存在,且不能复用:
✅ 正确做法:
- 每次请求都新建一个
new AbortController() - 把
controller.signal作为signal字段传进fetch的第二个参数(init对象) - 保留对
controller实例的引用,后续才能调用abort()
❌ 常见错误:
- 复用同一个
controller:调用一次abort()后,它的signal永久进入aborted状态,再传给新fetch会立刻抛出AbortError - 漏传
signal或拼错字段名(比如写成signals或Signal) - 在
fetch().then()里才创建 controller —— 这时请求早已发出,signal 失效
const controller = new AbortController();
fetch('/api/data', {
signal: controller.signal // ✅ 必须这样传
}).catch(err => {
if (err.name === 'AbortError') {
console.log('请求被取消');
}
});
// 取消时:
controller.abort(); // ✅
取消后 catch 到的错误类型和判断方式
fetch 被取消时不会进 .then(),而是直接进 .catch(),但错误对象不是通用的 Error,而是 DOMException,且 name 为 "AbortError"。
注意点:
-
err.name === 'AbortError'是最可靠判断方式;不要依赖err.message(不同浏览器内容不一致) - 某些环境(如旧版 Safari)可能不抛
AbortError,而是静默失败,所以建议配合超时或状态标记做兜底 - 如果用了
async/await,需用try/catch捕获,且catch块里必须显式检查err.name
try {
const res = await fetch('/api/search', { signal });
const data = await res.json();
} catch (err) {
if (err.name === 'AbortError') {
// ✅ 安全取消处理
} else {
// 其他网络或解析错误
}
}
实际场景中容易忽略的边界问题
真实项目里,取消逻辑往往嵌套在组件生命周期、防抖、多请求协同等上下文中,几个硬坑:
- React 中组件卸载后仍尝试
abort():虽然无害,但 controller 可能已被垃圾回收,或 signal 已销毁,建议加一层 if (controller.signal.aborted === false) 判断
- 多个并发请求共用一个 controller:取消一个会连带干掉所有,应按需独立控制(例如每个搜索请求配一个 controller)
- 没清理引用导致内存泄漏:尤其在闭包或事件监听器中持有 controller,记得在不需要时置为
null 或解除绑定
- 服务端其实收到了请求:Abort 只中断客户端接收,并不通知服务端停止处理,后端仍可能执行完整逻辑(这点常被误认为“请求真被取消了”)
真正难的不是写那行 controller.abort(),而是想清楚「谁负责取消」「何时取消」「取消后 UI 和状态怎么同步」——这些没法靠 API 解决,得靠设计。
abort():虽然无害,但 controller 可能已被垃圾回收,或 signal 已销毁,建议加一层 if (controller.signal.aborted === false) 判断null 或解除绑定前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











