1. 基本概念
• AbortController 是一个用于取消异步任务(如 fetch
请求)的控制器对象。
• 包含:
• signal
属性:一个 AbortSignal
实例,用于通知异步任务何时被取消。
• abort()
方法:触发取消操作,使 signal
状态变为已中止。
2. 基本用法
const controller = new AbortController();
const { signal } = controller;
// 将 signal 传递给支持取消的异步操作(如 fetch)
fetch('https://api.example.com/data', { signal })
.then(response => response.json())
.catch(err => {
if (err.name === 'AbortError') {
console.log('请求被取消');
}
});
// 取消请求
controller.abort();
3. 核心特性
• signal.aborted
:布尔值,表示任务是否被取消。
• signal.reason
:获取调用 abort(reason)
时传递的原因,默认为 AbortError
。
• 事件监听:通过 signal.addEventListener('abort', callback)
监听取消事件。
4. 应用场景
• 取消重复请求:如搜索框输入防抖,取消前一次未完成的请求。
• 组件卸载清理:在 React 的 useEffect
清理函数中取消请求。
• 超时处理:结合 AbortSignal.timeout()
自动取消长时间未完成的请求。
5. 高级用法
a. 取消多个请求
const controller = new AbortController();
// 多个请求共享同一个 signal
fetch(url1, { signal: controller.signal });
fetch(url2, { signal: controller.signal });
// 同时取消所有请求
controller.abort();
b. 超时自动取消
// 使用 AbortSignal.timeout()(需注意浏览器兼容性)
fetch(url, { signal: AbortSignal.timeout(5000) })
.catch(err => {
if (err.name === 'TimeoutError') {
console.log('请求超时');
}
});
c. 组合多个 Signals
// 当任一 signal 被取消时,触发中止
const combinedSignal = AbortSignal.any([signal1, signal2]);
d. 自定义异步任务支持 Abort
function delay(ms, signal) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => resolve(), ms);
signal?.addEventListener('abort', () => {
clearTimeout(timer);
reject(new DOMException('任务被取消', 'AbortError'));
});
});
}
6. 错误处理
• 捕获 AbortError
并区分其他错误:
fetch(url, { signal })
.catch(err => {
if (err.name === 'AbortError') {
// 处理取消逻辑
} else {
// 处理其他错误
}
});
7. React 示例(组件卸载时取消)
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(/* ... */);
return () => controller.abort(); // 清理函数中取消
}, []);
8. 兼容性与注意事项
• 浏览器支持:现代浏览器均支持,IE 不支持。Node.js 需 v15+。
• 不可重用:一个 AbortController
只能取消一次,后续需新建实例。
• 第三方库:如 Axios 支持通过 signal
取消请求:
const source = axios.CancelToken.source();
axios.get(url, { cancelToken: source.token });
source.cancel();
9. 最佳实践
• 及时清理:在异步任务完成后移除事件监听,避免内存泄漏。 • 复用 Signal:合理设计 Signal 的作用域,避免不必要的控制器实例。 • 结合框架:在 SPA 框架中,利用生命周期钩子统一管理异步任务。
10. 静态方法(新增 API)
• AbortSignal.abort(reason)
:返回一个已中止的 Signal。
• AbortSignal.any(signals)
:任意 Signal 中止时触发。
• AbortSignal.throwIfAborted()
:在异步任务中主动检查是否中止。
通过合理使用 AbortController
,可以有效管理异步任务的生命周期,提升应用性能和用户体验。