使用 AbortController 清理未完成搜索请求,需在组件卸载或路由跳转前调用 abort();React 在 useEffect 清理函数中、Vue3 在 onBeforeUnmount 中、原生 JS 监听 beforeunload 或路由事件;每次请求新建 controller 并传 signal,防抖时需同步取消;捕获并忽略 AbortError。

页面切换时用 AbortController 清理未完成的搜索请求,核心是:在组件卸载或路由跳转前调用 controller.abort(),让正在发起的 fetch 请求主动中止,避免内存泄漏、状态错乱或无效渲染。
监听页面离开或组件卸载时机
不同场景下触发清理的时机不同:
-
React 函数组件:在
useEffect的清理函数中调用abort() -
Vue 3(Composition API):在
onBeforeUnmount或onScopeDispose中调用 -
原生 JS 单页应用:监听
beforeunload或路由变化事件(如popstate、hashchange),或在手动跳转前显式 abort
为每次搜索请求创建独立的 AbortController
不能复用同一个 AbortController 实例处理多个请求,否则一次 abort 会中断所有关联请求。应确保:
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
- 每次调用搜索函数(如用户输入后 debounce 触发)都新建
new AbortController() - 将
controller.signal传入fetch的options中 - 保存当前 controller 引用(例如用 ref),以便后续清理
示例(React):
const searchRef = useRef(null);
const doSearch = async (query) => {
// 清掉上一次未完成的请求
if (searchRef.current) searchRef.current.abort();
const controller = new AbortController();
searchRef.current = controller;
try {
const res = await fetch(`/api/search?q=${query}`, {
signal: controller.signal
});
const data = await res.json();
// 更新状态...
} catch (err) {
if (err.name === 'AbortError') return; // 忽略中止错误
console.error('搜索失败:', err);
}
};
配合防抖和自动清理更可靠
搜索常带防抖(debounce),此时要特别注意:防抖回调执行前若页面已离开,需确保 controller 被及时 abort。建议:
- 在防抖函数外层维护 controller 引用,并在防抖被取消或组件卸载时 abort
- 使用支持取消的防抖库(如
lodash.cancelableDebounce),或自己封装带 cancel 方法的防抖 - 在
useEffect清理函数中,除了 abort,也调用防抖 cancel,双重保险
注意 fetch 中止后的错误处理
AbortController 中止后,fetch 会抛出 AbortError,必须捕获并忽略,否则会变成未处理异常:
- 务必在
catch中判断err.name === 'AbortError' - 不要把中止当失败处理(比如显示“请求失败”提示)
- 避免因中止错误导致后续逻辑(如 loading 状态未关闭)卡住

















