You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VueJS与Axios:中止网络请求后组件加载状态不更新

问题根源

原方案失效的核心是被中止请求的finally回调会覆盖新请求的loading状态,具体执行顺序如下:

  1. 触发fetchData后,首先同步执行CANCEL_PENDING_REQUESTS,中止所有待处理请求——这些请求的catch和finally会被加入微任务队列等待执行。
  2. 同步设置loadingSpendingCard = true,此时loading为true。
  3. 发送新请求(同步操作)。
  4. 当前同步代码执行完毕,事件循环处理微任务队列,所有被中止请求的finally回调依次执行,将loadingSpendingCard设为false——刚设置的true直接被覆盖,导致新请求的loading不生效。

对于20+请求的场景,批量中止会触发大量finally回调,批量重置loading状态,问题更突出。

解决方案

你尝试的“请求取消时不重置loading”是正确方向,可优化为适配多请求的通用方案:

  • 在Axios请求拦截器中,给每个请求绑定AbortController的同时,携带对应loading状态的标识(比如loadingKey),并将控制器和标识存入VueX。
  • 在请求的catch中,用axios.isCancel(error)判断是否是取消错误,仅处理非取消的异常。
  • 在finally中,仅当请求未被取消时,才将对应loading设为false。

示例调整代码:

// 请求拦截器配置
axiosApiClient.interceptors.request.use(config => {
  const controller = new AbortController();
  config.signal = controller.signal;
  // 把控制器和loading标识存入VueX
  this.$store.commit('ADD_PENDING_REQUEST', { 
    controller, 
    loadingKey: config.loadingKey 
  });
  return config;
});

// 组件内fetchData方法
methods: {
  fetchData() {
    this.$store.dispatch("CANCEL_PENDING_REQUESTS");
    this.loadingSpendingCard = true;
    
    axiosApiClient.get("/user-spending", {
      loadingKey: 'loadingSpendingCard' // 传递当前请求对应的loading标识
    })
    .then(res => console.log(res))
    .catch(err => {
      // 仅处理非取消的错误
      if (!axios.isCancel(err)) console.error(err);
    })
    .finally(() => {
      // 判断当前请求是否被取消,未取消才重置loading
      // 可通过VueX中记录的已取消请求列表,或在catch中标记状态
      if (!this.currentRequestCancelled) {
        this.loadingSpendingCard = false;
      }
    });
  }
}

另外,也可以把所有loading状态统一托管到VueX:取消请求时不修改loading,新请求发起时直接将对应loading设为true,请求完成(非取消)时设为false,彻底避免多个请求的回调互相干扰。

内容的提问来源于stack exchange,提问作者Zayed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 07:28:12