AbortController 可安全中止组件卸载时的异步操作,防止报错和内存泄漏;需为每个副作用单独创建 controller,在 useEffect 清理函数中调用 abort(),并区分 AbortError 与其它错误。

在 React 等组件化框架中,用 AbortController 可以安全地中止组件卸载时仍在进行的异步操作(比如 fetch 请求、setTimeout、setInterval 或自定义 Promise),避免“更新已卸载组件”报错或内存泄漏。
1. 基础用法:配合 fetch 请求
AbortController 的 signal 可传给 fetch,当调用 abort() 时,正在进行的请求会立即 reject 并抛出 AbortError。
在函数组件中,通常在 useEffect 内创建控制器,并在清理函数中调用 abort():
useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(res => res.json())
.then(data => setData(data))
.catch(err => {
if (err.name === 'AbortError') {
// 请求被取消,无需处理(不 setState)
} else {
setError(err.message);
}
});
return () => controller.abort(); // 组件卸载或依赖变化时取消
}, []);
2. 封装成可复用的自定义 Hook
手动管理每个请求的 AbortController 容易重复。可以封装一个 useAbortableFetch 或直接在请求前统一注入 signal:
立即学习“Java免费学习笔记(深入)”;
- 每次调用都新建
AbortController,确保隔离性 - 清理函数必须存在,且只调用一次
abort() - 注意:不能在异步回调里再检查
signal.aborted后调用setState,因为组件可能已卸载
3. 处理非 fetch 场景(如 setTimeout / Promise)
AbortSignal 提供了 aborted 属性和 addEventListener('abort', ...),可用于监听取消事件:
useEffect(() => {
const controller = new AbortController();
const timer = setTimeout(() => {
if (!controller.signal.aborted) {
setData('loaded after delay');
}
}, 2000);
// 或监听 abort 事件
controller.signal.addEventListener('abort', () => {
clearTimeout(timer);
});
return () => controller.abort();
}, []);
4. 注意事项与常见坑
- 不要复用同一个 controller:多个请求共用一个 signal,abort 会一并取消所有,应为每个副作用单独创建
-
避免在已 reject 的 Promise 中 setState:务必在
catch中判断err.name === 'AbortError',跳过状态更新 - React 18 严格模式下 useEffect 会执行两次:这会让 controller 先创建再 abort,再创建再 abort——只要逻辑正确(abort 不会报错),不影响功能
-
不支持 IE:若需兼容旧浏览器,可用 polyfill 或降级为手动标志位(如
let isMounted = true)


















