AbortController 可主动退出 async 函数执行流程,核心是使 await 的 Promise 拒绝并在 catch 中清理;需将 signal 传入支持取消的 API(如 fetch)或手动监听 abort 事件,普通 Promise 忽略 signal;可提前检查 signal.aborted 避免无谓等待;同一 signal 支持多请求联动取消;常与 useEffect 清理配合;结合 Promise.race 实现取消+超时双保险。

async 函数本身不能被“中途打断”,但可以通过 AbortController 主动退出执行流程——关键不是中断 await,而是让 await 的 Promise 拒绝,并在 catch 中做清理和提前返回。
AbortController 信号必须传入支持取消的异步操作
fetch 是原生支持 signal 的典型 API;自定义 Promise 需手动监听 abort 事件。如果 async 函数里只调用了普通 Promise(比如 setTimeout 封装的),不加信号监听,abort() 就不会触发任何响应。
- ✅ 正确:fetch('/api/data', { signal }) 或 new Promise((_, reject) => signal.addEventListener('abort', () => reject(new DOMException('AbortError'))))
- ❌ 错误:await new Promise(r => setTimeout(r, 1000)) —— 这个 Promise 完全忽略 signal,abort() 对它无效
在 async 函数中检查 signal.aborted 状态
除了依赖 Promise 拒绝,也可以在 await 前主动判断 signal 是否已被中止,避免无谓等待。尤其适合长耗时逻辑分段执行的场景。
- 用 signal.aborted 判断是否已取消,立即 throw 新的 AbortError
- 例如:if (signal.aborted) throw new DOMException('Operation aborted', 'AbortError')
- 配合 try/catch 可统一处理取消和其他错误,也便于记录日志或重置 UI 状态
共享 signal 实现多个请求联动取消
一个 AbortController 的 signal 可被多个 fetch、多个自定义 Promise 同时使用。调用一次 abort(),所有绑定该 signal 的操作都会被终止——这是解决搜索联想 + 主请求、分页切换、表单多字段校验等竞态问题的核心技巧。
- 搜索框每输入一次,先 abort 上一个 controller,再新建 controller 并把 signal 传给建议请求和主搜索请求
- React 中常配合 useEffect 清理函数,在组件卸载时调用 controller.abort()
- 注意:signal 是只读属性,不可重复赋值;每次新请求都应创建新 controller
与超时控制组合使用更稳妥
单纯靠 abort() 无法应对网络卡死、服务无响应等情况。可将 AbortController 和 Promise.race 配合 timeout Promise,实现“手动取消 + 自动超时”双保险。
- 构造 timeout Promise:new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 8000))
- 和带 signal 的 fetch Promise 一起 race,任一拒绝即退出
- catch 中区分 AbortError 和 TimeoutError,分别做不同反馈(如“已取消” vs “请求超时,请重试”)


















