在 Vue3 中,AbortController
用于取消 fetch
请求,避免组件卸载后仍执行异步操作导致的潜在问题(如内存泄漏或更新已销毁组件的状态)。以下是详细用法和最佳实践:
一、基本用法
创建
AbortController
实例
在组件setup()
中创建实例,并通过signal
关联请求:javascript
import { onUnmounted } from 'vue'; export default { setup() { const controller = new AbortController(); const signal = controller.signal; // 发送请求时传递 signal fetch('/api/data', { signal }) .then(response => response.json()) .catch(err => { if (err.name === 'AbortError') { console.log('请求已取消'); } else { console.error('请求失败:', err); } }); // 组件卸载时取消请求 onUnmounted(() => controller.abort()); return {}; }, };
二、结合异步操作
在异步函数中结合 AbortController
:
javascript
import { onUnmounted } from 'vue'; export default { setup() { const controller = new AbortController(); const fetchData = async () => { try { const response = await fetch('/api/data', { signal: controller.signal }); const data = await response.json(); // 处理数据 } catch (err) { if (err.name === 'AbortError') { console.log('请求已取消'); } else { console.error('请求失败:', err); } } }; fetchData(); onUnmounted(() => controller.abort()); }, };
三、管理多个请求
单个 AbortController
可取消多个请求:
javascript
const controller = new AbortController(); // 请求1 fetch('/api/data1', { signal: controller.signal }); // 请求2 fetch('/api/data2', { signal: controller.signal }); // 取消所有请求 controller.abort();
四、与 Axios 结合使用
如果使用 Axios,可通过 CancelToken
(旧版)或 AbortController
(Axios >= 0.22.0)取消请求:
javascript
import axios from 'axios'; const controller = new AbortController(); axios.get('/api/data', { signal: controller.signal, }) .then(response => { /* ... */ }) .catch(err => { if (axios.isCancel(err)) { console.log('请求已取消'); } }); // 取消请求 controller.abort();
五、注意事项
兼容性
AbortController
在现代浏览器中支持良好,但需考虑旧版浏览器兼容性(可通过polyfill
解决)。错误处理
捕获AbortError
避免未处理的 Promise 拒绝。复用 Controller
每次新请求前创建新的AbortController
,避免重复使用已取消的实例。
六、最佳实践
在组件卸载时取消请求:在
onUnmounted
生命周期钩子中调用abort()
。封装可复用的逻辑:将取消逻辑封装到自定义 Hook 中(如
useFetch
)。避免内存泄漏:确保所有未完成的请求在组件销毁时被取消。
通过合理使用 AbortController
,可以有效管理 Vue3 中的异步操作,提升应用性能和稳定性。
// 获取配置项内容
export const selectOptionsService = (optionItemId: string, signal?: AbortSignal) => {
return request.get("selectOptions/SystemOptions", {
params: {
optionItemId: optionItemId
},
// 设置 signal 信号属性,后续就可以通过 abort 取消请求
signal: signal
});
};
......
// 创建 AbortController 用于取消请求
const controller = new AbortController();
// 并发加载多个选项
const [wspjTypeResult, cyTypeResult, payTypeResult] = await Promise.allSettled([
// 设置信号 AbortSignal,关联请求,以便能取消请求
usePostServiceHook(selectOptionsService, ["lbWSPJType", controller.signal]),
usePostServiceHook(selectOptionsService, ["cyType", controller.signal]),
usePostServiceHook(selectOptionsService, ["lbFAX", controller.signal])
]);
onUnmounted(() => {
// 取消请求
controller.abort();
});
......