在前端开发中,取消网络请求是一个常见的需求,尤其是在用户频繁操作或需要中断长时间请求的场景下。
AbortController 主要用于 优雅地管理和取消异步操作:
浏览器原生 API
一、代码解析
1. 创建 AbortController 实例
const controller = new AbortController();
- 作用:实例化一个
AbortController
对象,用于生成AbortSignal
信号对象。 - 返回值:
controller
包含两个属性:signal
:用于传递给支持取消的 API的信号对象abort()
:调用此方法会触发信号的中止逻辑
2. 发起可取消的 fetch 请求
fetch(url, { signal }).then(response => response.json()).catch(error => {if (error.name === 'AbortError') {console.log('请求已取消');}});
关键点:
- 将
controller.signal
作为fetch
的第二个参数传入,使请求与信号关联 - 当
controller.abort()
被调用时,fetch
请求会检测到signal.aborted
为true
,终止请求并抛出AbortError
- 错误处理:通过
catch
捕获错误,判断error.name === 'AbortError'
以区分请求是否被主动取消
3. 终止请求
controller.abort(); // 终止请求
原理==信号机制==:
AbortController
通过signal
对象实现跨 API 的取消信号传递- 当
abort()
被调用时,所有关联的signal
会触发abort
事件,通知相关操作终止
一、核心应用场景
1.取消网络请求
在用户频繁操作(如快速切换页面、重复提交表单)时,避免因多个未完成的请求导致 竞态条件
示例:用户连续点击“加载数据”按钮时,仅保留最后一次请求的结果,中断之前的请求
const controller = new AbortController();
fetch(url, { signal }).then(response => response.json()).catch(error => {if (error.name === 'AbortError') {console.log('请求已取消');}});
controller.abort(); // 终止请求
2.超时控制
结合 AbortSignal.timeout()
自动终止超时请求,避免长时间等待无响应的接口
fetch('/api/data', { signal: AbortSignal.timeout(5000) }) // 5秒超时.then(response => response.json()).catch(error => {if (error.name === 'TimeoutError') {console.log('请求超时');}});
二、实际应用场景
1.搜索框防抖取消
用户连续输入时,仅保留最后一次请求
const search = debounce(async (query) => {if (controller.value) controller.value.abort();controller.value = new AbortController();const response = await fetch(`/api/search?q=${query}`, { signal: controller.value.signal });// 更新搜索结果
}, 300);
2.分页加载控制
切换分页时取消上一页请求:
const loadPage = async (page) => {if (controller.value) controller.value.abort();controller.value = new AbortController();const data = await fetch(`/api/data?page=${page}`, { signal: controller.value.signal });// 渲染新数据
};
三、技术优势
- 统一控制流
通过单一AbortController
实例管理多个异步操作,简化代码逻辑 - 避免资源浪费
及时终止无效请求,减少网络带宽和服务器压力 - 兼容性适配
现代浏览器广泛支持,低版本环境可通过 Polyfill 兼容