在 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 中的异步操作,提升应用性能和稳定性。
TypeScript
// 获取配置项内容
export const selectOptionsService = (optionItemId: string, signal?: AbortSignal) => {
return request.get("selectOptions/SystemOptions", {
params: {
optionItemId: optionItemId
},
// 设置 signal 信号属性,后续就可以通过 abort 取消请求
signal: signal
});
};
TypeScript
......
// 创建 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();
});
......