abortcontroller 是浏览器原生用于中止异步操作的机制,通过 signal 统一控制 fetch 请求、定时器、事件监听器等资源的生命周期,调用 abort() 即可同步清理所有关联资源,避免内存泄漏和状态不一致。

AbortController 是浏览器原生提供的用于中止异步操作的机制,它能统一管理请求取消、事件监听器移除等资源清理逻辑,避免内存泄漏和状态不一致。核心在于用同一个 signal 关联多个可取消操作,并在适当时机调用 abort()。
一、用 signal 控制 fetch 请求生命周期
现代 fetch 原生支持 signal 选项,请求会在 signal 触发 abort 时自动终止并抛出 AbortError:
- 创建控制器:const controller = new AbortController();
- 发起请求时传入 signal:fetch(url, { signal: controller.signal })
- 主动取消:controller.abort() —— 此时 fetch Promise 立即 reject,且不会触发后续 then/catch 中的副作用
注意:不能重复调用 abort(),多次调用无副作用,但 signal 的 aborted 属性变为 true 后不可逆。
二、扩展 signal 到自定义异步操作(如定时器、轮询)
AbortController 不仅限于 fetch,任何异步逻辑都可通过监听 signal.aborted 或 signal.addEventListener('abort', ...) 做响应:
- 轮询场景:在 setInterval 回调开头检查
if (signal.aborted) clearInterval(id); return; - Promise 封装:用
Promise.race([promise, new Promise((_, rej) => signal.addEventListener('abort', () => rej(new DOMException('Aborted', 'AbortError'))))])包裹任意异步任务 - 避免手动清除:优先用 signal 监听代替 try/finally + clearTimeout,语义更清晰、不易遗漏
三、统一绑定与解绑事件监听器
addEventListener 支持 { signal } 选项,让监听器随 controller.abort() 自动移除:
- 添加监听:elem.addEventListener('click', handler, { signal: controller.signal });
- 无需再单独调用 removeEventListener —— abort 后浏览器自动清理
- 适用于 document、window、自定义元素等所有支持 addEventListener 的目标
- 特别适合组件卸载(如 React useEffect cleanup、Vue onUnmounted)时一键释放全部监听
四、组合多个资源,共用一个 controller 实现“原子级”清理
一个 AbortController 可同时控制多个异步资源,确保它们被同步中止:
- 典型场景:页面加载时发起 API 请求 + 启动心跳定时器 + 绑定键盘快捷键监听
- 全部使用同一 controller.signal,组件销毁或路由跳转时只需 controller.abort(),所有关联资源自动释放
- 避免因某个清理步骤遗漏(如忘了 clearTimeout)导致后台任务持续运行
- 搭配 async/await 使用时,建议将 controller 创建放在最外层作用域,便于集中管理
不复杂但容易忽略:AbortController 是轻量对象,无需复用;每个独立业务逻辑应创建自己的 controller,避免跨作用域误 abort。










