应优先使用 onCleanup 标记请求过期或 AbortController 中断请求,配合防抖、缓存去重和按钮禁用等策略,确保仅最新筛选结果生效并防止内存泄漏。

在 Vue 3 的条件筛选场景中(比如下拉筛选、多选标签、时间范围切换),每次参数变化都触发新请求,但旧请求若未完成就返回,会覆盖最新结果——页面显示的数据和当前筛选条件不一致。这不是 bug,而是异步竞态的自然表现。关键不是“阻止多次请求”,而是确保只有最后一次请求的结果生效。
用 onCleanup 标记过期请求
watch 或 watchEffect 的回调支持第三个参数 onCleanup,它会在下一次监听触发前执行,适合做“标记失效”操作:
- 每次请求开始前设一个
let isLatest = true标志 - 调用
onCleanup(() => { isLatest = false }) - 请求完成后只在
if (isLatest)时更新响应数据
这种方式轻量、无需额外依赖,适用于大多数简单筛选逻辑,且不中断网络连接,只是忽略旧响应。
用 AbortController 真正中断 fetch 请求
如果后端接口响应慢、带宽敏感,或需立即释放连接(如图片预览、大文件查询),应使用标准的 AbortController:
立即学习“前端免费学习笔记(深入)”;
- 每次请求前创建新的
new AbortController() - 将
signal传给fetch或axios配置项 - 在
onCleanup中调用controller.abort()
注意:Axios v0.22+ 原生支持 signal,无需 CancelToken;旧版本需升级或适配 polyfill。
在路由或组件卸载时自动清理
筛选组件可能被销毁(如 Tab 切换、路由跳转),此时未完成的请求仍可能回填数据,造成内存泄漏或报错:
- 在
onBeforeUnmount中手动调用abortController?.abort() - 或统一用
onCleanup—— 它在组件卸载时也会执行,一并覆盖了卸载清理场景
不需要额外判断“是否还在组件内”,onCleanup 已涵盖监听重触发和组件销毁两种时机。
避免重复请求的辅助策略
单纯取消还不够,可叠加以下实践提升健壮性:
- 防抖输入类筛选:对搜索框等高频输入字段加 300ms 防抖,减少请求数量
- 请求缓存键去重:相同参数组合的请求,可缓存 Promise 实例,避免并发重复发
- 按钮禁用 + loading 状态:视觉反馈 + 阻断用户二次触发,从源头降低竞态概率
这些不是替代取消机制,而是协同配合,让筛选交互更稳更顺。


















