避免重复请求,请求防抖

const res: any = await getBaseData({
      ...queryParams.value
    }, {
      signal: abortController.value.signal  // 传递取消信号
    });

这段代码使用了 Axios 的请求取消(Request Cancellation) 机制。

核心含义

signal: abortController.value.signal 的作用是将当前的 HTTP 请求与一个 AbortController 控制器绑定。当这个控制器被调用 abort() 方法时,正在进行的网络请求会被立即中断(取消),从而节省带宽、减少服务器压力,并避免旧请求的数据覆盖新请求的数据(竞态条件)。

详细解析

1. AbortController 是什么?

AbortController 是一个原生 JavaScript API,用于控制一个或多个 DOM 请求(如 fetchaxios)。

  • 创建new AbortController() 创建一个控制器实例。
  • 信号controller.signal 是一个对象,包含请求的状态。
  • 取消controller.abort() 会触发信号,通知所有监听该信号的请求“停止”。

2. 在代码中是如何工作的?

请看完整逻辑:

const getList = async () => {
  // 1. 【关键步骤】如果之前有一个未完成的请求,先强制取消它
  if (abortController.value) {
    abortController.value.abort(); 
  }
  
  // 2. 【关键步骤】创建一个新的控制器,用于管理本次请求
  abortController.value = new AbortController();

  try {
    loading.value = true;
    // 3. 【关键步骤】将新控制器的 signal 传递给 axios
    const res: any = await getBaseData({
      ...queryParams.value
    }, {
      signal: abortController.value.signal  // <--- 这里绑定信号
    });
    
    comPartsNoticeList.value = res?.data || [];
  } catch (error: any) {
    // 4. 【关键步骤】捕获取消错误
    if (error.name === 'AbortError' || error.message?.includes('canceled')) {
      console.log('请求已取消,忽略响应');
      return; // 如果是被取消的,直接返回,不处理数据
    }
    // 处理其他真实错误...
  } finally {
    loading.value = false;
  }
};

3. 为什么要这么做?(应用场景)

在定时刷新场景中,这非常重要:

  • 防止竞态条件(Race Condition)
    假设用户快速点击了“手动刷新”按钮两次,或者定时器触发时上一个请求还没回来。

    • 没有取消机制:第一个请求可能比第二个请求晚返回。结果就是:界面先显示第二次请求的数据,然后突然跳变回第一次请求的旧数据。这会导致数据不一致。
    • 有取消机制:第二次点击时,代码执行 abortController.value.abort()第一个请求直接被杀死。只有第二个请求会成功返回并更新界面。保证界面永远显示最新的请求结果。
  • 节省资源
    如果用户频繁改变请求参数,或者快速刷新,旧的、不再需要的请求会被立即终止,不再占用浏览器和服务器的资源。

  • 组件卸载时清理
    onUnmounted 中:

    onUnmounted(() => {
      stopTimer();
      if (abortController.value) {
        abortController.value.abort(); // 组件销毁时,如果还有请求在跑,立即取消
        abortController.value = null;
      }
    });
    

    这防止了组件销毁后,异步请求回来尝试更新已销毁组件的状态(这通常会导致 Vue 警告或内存泄漏)。

总结

代码部分 作用
new AbortController() 创建一个“遥控器”,用于控制本次请求。
signal: ... 把“遥控器”的信号接收器交给 Axios。Axios 会监听这个信号。
abortController.value.abort() 按下“遥控器”的取消键。Axios 收到信号后,立即中断网络请求,抛出 AbortError
catch (error) 中的判断 区分是“正常网络错误”还是“我主动取消的错误”。如果是主动取消,则静默忽略。

这是一种最佳实践,特别是在高频刷新、搜索防抖或单页应用(SPA)路由切换的场景中。

posted @ 2026-07-07 16:30  Amnesia_999  阅读(3)  评论(0)    收藏  举报