Vue 3 中用 AbortController 实现全局重复请求取消:根据 method+url+params 生成唯一 key,用 Map 缓存 controller,重复时 abort 旧请求再发新请求,响应后非 cancel 错误才清理 key。

在 Vue 3 项目中,通过全局请求拦截器统一管理重复请求的取消,核心思路是:**对每个待发请求生成唯一标识(如 method + url + params 序列化),若该标识已存在未完成请求,则主动中止旧请求,再发起新请求**。这比单个组件内手动 cancel 更可靠,也避免了多页面、多模块间状态不一致的问题。
用 AbortController 实现请求唯一标识与自动中断
现代 axios(v0.22.0+)推荐使用标准 AbortController 替代已废弃的 CancelToken。它更轻量、原生支持,且能自然融入拦截器生命周期:
- 在请求拦截器中,为每个请求创建
new AbortController(),将controller.signal挂载到 config.signal 上 - 同时,根据请求方法、URL 和规范化后的参数(如 JSON.stringify(params) 或 query string)生成唯一 key
- 用 Map 或对象缓存 { key → controller },若 key 已存在,先调用旧 controller.abort(),再覆盖为新 controller
在 request.ts 中封装拦截逻辑(推荐 TS 写法)
以 src/utils/request.ts 为例,配合 Pinia 存储管理 pending 请求:
将静态 Vue 页面(index.vue)改造为动态页面(Custom.vue);稿源仅限 index.vue、其引用的 CSS 与资源路径,禁止参考仓库内其他文件。Invoke when user wants to transform a static Vue page into a dynamic data-driven page with Element UI components.
- 定义一个
pendingMap = new Map<string abortcontroller>()</string> - 请求拦截器中计算 key:
const key = [config.method, config.url, JSON.stringify(config.params || {})].join('|') - 若
pendingMap.has(key),执行pendingMap.get(key)?.abort(),再 set 新 controller - 响应拦截器或错误拦截器中,无论成功或失败(非 abort 错误),都调用
pendingMap.delete(key)
注意 key 的合理性,避免误判重复
不是所有相同 URL 都该被取消。比如分页列表的 /api/list?page=1 和 /api/list?page=2 是不同请求,必须区分:
立即学习“前端免费学习笔记(深入)”;
- 只对「语义等价」的请求去重:例如搜索接口
/api/search?q=vue连续触发多次,应取消前序 - 可加白名单机制:对需严格保序的接口(如提交订单),跳过取消逻辑
- 参数序列化前建议过滤掉时间戳、随机数等干扰字段,否则 key 总不同,失去意义
响应拦截器里清理要区分 cancel 场景
axios 错误对象中,error.code === 'ERR_CANCELED' 表示是主动 abort 导致,并非网络失败。因此在响应拦截器的 error 分支中:
- 检查
error.config是否存在,再取其 key - 仅当
error.code !== 'ERR_CANCELED'时才清理 pendingMap(避免重复删) - 否则说明是正常响应完成,可安全 delete

















