Vue 3分页竞态控制关键是在发起新请求前取消旧请求,推荐用AbortController管理:每次fetchPage时创建新controller并存为ref,旧的调abort();多参数时按完整URL生成key存Map;封装为usePaginationRequest组合式函数复用,并在响应拦截器中静默处理AbortError。

在 Vue 3 分页场景中,用户快速点击“上一页”“下一页”时,若前一页的请求还没返回,新请求已发出,就容易出现数据错乱(比如第3页数据覆盖了刚返回的第2页结果)。解决的关键是:**每次发起新分页请求前,主动取消上一次同类型未完成的请求**。这不需要等路由跳转,而是聚焦于同一页面内分页操作的竞态控制。
用 AbortController 管理单个分页请求
这是目前最推荐的方式,符合浏览器标准,无需依赖 axios 旧版 CancelToken。
- 每次调用分页方法(如 fetchPage(2))时,先创建新的 AbortController 实例,并把它的 signal 挂到 axios 配置里
- 将该 controller 存为组件级响应式变量(如 currentPageController),覆盖上一次的引用
- 在发起新请求前,检查是否存在旧 controller,有则调用 .abort()
示例逻辑:
const currentPageController = ref(null)const fetchPage = async (pageNum) => {
if (currentPageController.value) {
currentPageController.value.abort('new page requested')
}
currentPageController.value = new AbortController()
try {
const res = await axios.get('/api/list', {
params: { page: pageNum },
signal: currentPageController.value.signal
})
// 渲染数据
} catch (err) {
if (err.name === 'AbortError') return // 忽略取消错误
// 处理其他错误
}
}
按分页参数做请求唯一标识(适合多条件分页)
当分页还带搜索、筛选等参数时,仅靠页码不够区分;此时可对完整请求配置生成唯一 key(如 `GET:/api/list?search=a&page=2&size=10`),再用 Map 缓存每个 key 对应的 controller。
Element Plus Vue3 桌面组件库。在开发 Vue 3.x 页面时调用,使用 Element Plus 组件(如 el-button、el-input、el-form、el-table 等)。
- 定义一个响应式 Map:const pendingRequests = reactive(new Map())
- 请求前计算 key,若有旧 controller 就 abort 并删除
- 新 controller 存入 Map,请求结束后记得 delete 对应 key(可在 .finally 或响应拦截器中清理)
配合组合式函数封装复用逻辑
把上述流程抽成自定义 Hook,比如 usePaginationRequest(),对外只暴露 load(page, params) 和 abortAll() 方法,让多个分页表格组件都能一致使用。
- 内部自动处理 controller 生命周期和 key 管理
- 支持手动取消(如用户点击“停止加载”按钮)
- 可扩展加载状态、错误重试等能力,不污染业务组件
注意响应拦截器里的静默处理
被 abort 的请求会进 axios 响应错误拦截器,抛出 AbortError。务必在这里判断并 不 reject Promise,避免触发业务层的错误提示或 loading 状态卡死:
axios.interceptors.response.use(res => res,
err => {
if (err.name === 'AbortError') return Promise.resolve() // 静默吞掉
return Promise.reject(err)
}
)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









