AbortController 与异步取消

解释 AbortController 和 AbortSignal 如何传播取消意图,以及 fetch、流读取和 React effect 应如何共同管理任务生命周期。

#type / concept #status / evergreen #tech / dev / frontend #resource / javascript #platform / browser

[!info] related notes

AbortController 与异步取消

一句话定义

AbortController 创建和触发取消,AbortSignal 把取消状态传给支持它的异步 API;取消是协作协议,不是强制杀死任意 JavaScript 函数。

const controller = new AbortController();

try {
  const response = await fetch(url, { signal: controller.signal });
  // 继续读取 response.body
} catch (error) {
  if (error instanceof DOMException && error.name === 'AbortError') {
    return;
  }
  throw error;
}

所有权

启动任务的一方通常负责:

  • 持有 controller
  • 在用户取消、组件卸载或新任务替代旧任务时调用 abort()
  • 区分预期取消和真实失败

下游函数接收 AbortSignal,不应随意替调用方决定何时取消整个任务。

React effect

useEffect(() => {
  const controller = new AbortController();
  void loadData(controller.signal);
  return () => controller.abort();
}, [key]);

清理函数使旧 effect 的任务在依赖变化或组件卸载时停止。它同时减少无意义网络工作和旧响应覆盖新状态的竞态。

取消流读取

把 signal 交给 fetch 通常会使 body 读取也失败退出。还应确保循环捕获取消异常、停止分发事件,并在需要时释放 reader。

常见误解

  • abort() 不会回滚已经发生的服务端副作用。
  • Promise 本身没有通用强制取消;必须由具体 API 协作。
  • 把取消当普通错误弹给用户会制造噪声。
  • 只用 isMounted 忽略结果不能停止网络和服务器工作。
创建于 2026/7/29 更新于 2026/7/29