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

如何在axios中设置两个互不干扰的拦截器,解决跨函数异常触发问题

问题原因
  • axios 默认实例的拦截器是全局生效的,和你声明时所在的函数作用域没有关系,只要注册成功,所有经过该实例的请求/响应都会触发对应拦截器
  • addUser 函数中存在低级错误:你注册的是 响应拦截器,卸载时调用的是 axios.interceptors.request.eject()(卸载请求拦截器的API),完全没有命中你要删除的响应拦截器,所以第一个拦截器会一直留在全局,后续所有响应都会触发它
  • findUser 函数中注册的响应拦截器完全没有做卸载逻辑,也会一直全局生效
修复方案

方案1:快速修复现有拦截器逻辑

注意要把卸载逻辑放到 finally 块中,避免请求报错时走不到卸载代码:

async function addUser(user) {
  const config = {
    headers: {
      "Content-Type": "application/json",
    },
  };
  let interceptorResponse = null;
  try {
    interceptorResponse = axios.interceptors.response.use(
      (response) => {
        if (typeof response.data === "object") {
          let success = response.data.registerSuccess;
          let errors = response.data.errors;
          let data = response.data.data;
          let message = response.data.message;
          setData(() => {
            return { ...data, errors, registerSuccess: success, message };
          });
        }
        return response;
      }
    );
    await axios.post("/users/register", user, config);
  } catch (err) {} finally {
    // 卸载对应的响应拦截器,且不管请求成功失败都执行
    if (interceptorResponse !== null) {
      axios.interceptors.response.eject(interceptorResponse);
    }
  }
}

async function findUser(user) {
  const config = {
    headers: {
      "Content-Type": "application/json",
    },
  };
  let interceptorResponse = null;
  try {
    interceptorResponse = axios.interceptors.response.use((response) => {
      console.log(response);
      if (typeof response.data === "object") {
        let loginSuccess = response.data.data.loginSuccess;
        let message = response.data.message;
        console.log(response.data);
        setData(() => {
          return { ...data, loginSuccess, message };
        });
      }
      return response;
    });
    await axios.post("/users/login", user, config);
  } catch (error) {} finally {
    if (interceptorResponse !== null) {
      axios.interceptors.response.eject(interceptorResponse);
    }
  }
}

注意:这个方案只适合单请求串行的场景,如果存在并发请求,临时注册的全局拦截器依然可能错误处理其他请求的响应。

方案2(更推荐):去掉不必要的拦截器,直接处理请求返回结果

你的场景只是单个请求的响应处理,完全不需要用拦截器,直接处理axios.post返回的响应即可,不会有任何全局污染:

async function addUser(user) {
  const config = {
    headers: {
      "Content-Type": "application/json",
    },
  };
  try {
    const response = await axios.post("/users/register", user, config);
    if (typeof response.data === "object") {
      let success = response.data.registerSuccess;
      let errors = response.data.errors;
      let data = response.data.data;
      let message = response.data.message;
      setData(() => {
        return { ...data, errors, registerSuccess: success, message };
      });
    }
  } catch (err) {}
}

async function findUser(user) {
  const config = {
    headers: {
      "Content-Type": "application/json",
    },
  };
  try {
    const response = await axios.post("/users/login", user, config);
    console.log(response);
    if (typeof response.data === "object") {
      let loginSuccess = response.data.data.loginSuccess;
      let message = response.data.message;
      console.log(response.data);
      setData(() => {
        return { ...data, loginSuccess, message };
      });
    }
  } catch (error) {}
}

如果确实有部分公共逻辑需要用拦截器,也可以用axios.create()为每个模块/场景创建独立的axios实例,不同实例的拦截器互相隔离,不会冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:06:03