Axios 取消请求
Axios 提供了两种主要的方式来取消请求:
1. 使用 CancelToken (旧版方式,已弃用但仍可用)
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log('请求已取消', thrown.message);
} else {
// 处理其他错误
}
});
// 取消请求
source.cancel('操作被用户取消');
2. 使用 AbortController (推荐的新方式,从 v0.22.0 开始)
AbortController 是 JavaScript 中用于中止异步操作的全局 API,通过其 signal 属性和 abort() 方法,可终止 Fetch 请求、事件监听、数据流等异步任务。
其核心能力包括统一管理多个异步操作的中止行为和简化资源清理逻辑。
核心概念与基础用法
组成部分。
AbortController 实例包含两个关键部分:
signal:一个 AbortSignal 对象,用于向异步 API 传递中止信号。
abort() 方法:触发 signal 的中止事件,标记异步操作为已中止状态。
基本代码结构。
const controller = new AbortController();
axios.get('/user/12345', {
signal: controller.signal
}).then(response => {
// 处理响应
}).catch(err => {
if (axios.isCancel(err)) {
console.log('请求已取消:', err.message);
} else {
// 处理其他错误
}
});
// 取消请求
controller.abort('操作被用户取消');
调用 abort() 后,所有关联的异步操作将立即终止并抛出 AbortError。
标题主要应用场景
网络请求控制
中断长时间未完成的 Fetch 请求。
避免用户重复提交请求(如搜索框输入防抖)。
事件监听自动清理
通过单个 signal 统一移除多个事件监听器,替代手动调用 removeEventListener。
框架集成
在 React 的 useEffect 钩子中集中清理副作用。
封装 Axios 请求拦截器实现全局重复请求取消。
使用注意事项
要点 说明
错误处理 需捕获 AbortError 并区分其他错误类型
兼容性 现代浏览器广泛支持,旧版本需 Polyfill
性能优化 避免滥用导致频繁请求中断,增加服务器负担
状态复用 已中止的 signal 不可重复使用,需重新创建实例
实际应用示例
在 React 组件中使用
import React, { useEffect } from 'react';
import axios from 'axios';
function UserComponent({ userId }) {
useEffect(() => {
const controller = new AbortController();
const fetchData = async () => {
try {
const response = await axios.get(`/api/users/${userId}`, {
signal: controller.signal
});
// 处理数据
} catch (err) {
if (axios.isCancel(err)) {
console.log('请求已取消:', err.message);
} else {
// 处理其他错误
}
}
};
fetchData();
return () => {
// 组件卸载时取消请求
controller.abort('组件卸载,取消请求');
};
}, [userId]);
return <div>用户信息展示</div>;
}
在 Vue 中取消重复请求
// 存储所有活跃请求的控制器
const activeRequests = new Map();
// 添加请求
function addRequest(config) {
const controller = new AbortController();
config.signal = controller.signal;
const url = `${config.method}:${config.url}`;
activeRequests.set(url, controller);
return config;
}
// 移除请求
function removeRequest(config) {
const url = `${config.method}:${config.url}`;
if (activeRequests.has(url)) {
activeRequests.delete(url);
}
}
// 取消重复请求
function cancelRequest(config) {
const url = `${config.method}:${config.url}`;
if (activeRequests.has(url)) {
activeRequests.get(url).abort('取消重复请求');
activeRequests.delete(url);
}
}
// 请求拦截器
axios.interceptors.request.use(config => {
cancelRequest(config); // 取消之前的相同请求
return addRequest(config);
});
// 响应拦截器
axios.interceptors.response.use(
response => {
removeRequest(response.config);
return response;
},
error => {
removeRequest(error.config);
return Promise.reject(error);
}
);
注意事项
- 取消请求会触发错误,需要使用
axios.isCancel()
来区分是取消错误还是其他错误 - 每个请求只能取消一次
- 取消请求后,Promise 会被 reject
- 在组件卸载时取消请求是良好的实践,可以避免内存泄漏
- 对于频繁触发的请求(如搜索框输入),取消之前的请求可以提升性能
AbortController 是现代浏览器原生支持的标准 API,推荐使用这种方式而不是旧的 CancelToken。