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

TS封装Axios 401刷新token后重试报错无法读取undefined的cancelToken属性

问题核心原因
  1. 参数传递错误:响应拦截器的错误回调中,你只提取了error.response传入handleError,但重试需要用到的原始请求配置config是挂载在顶层error对象上的,不在response里。你把response传入handleError后还将参数命名为error,直接导致后续取error.config拿到的是undefined,调用this.request(undefined)自然会报无法读取undefined的cancelToken属性。
  2. 请求拦截器漏返回配置:injectToken函数只在满足if条件时返回了config,不满足条件时没有任何返回值,axios会把请求配置设为undefined,后续所有依赖配置的操作都会报错。
  3. 错误边界缺失:handleError直接解构参数的status属性,没有判断参数是否为undefined(比如网络错误时error.response本身就是undefined),直接触发无法读取undefined的status属性报错。
  4. 请求拦截器错误回调漏返回:请求拦截器的错误回调只写了Promise.reject(error)没有加return,错误会被静默吞掉,变成成功状态的Promise,引发后续逻辑异常。
修复步骤
  1. 修改响应拦截器错误回调,把完整的error对象传入handleError,不要只传response
  2. 补全injectToken函数的返回逻辑,所有分支都要返回config
  3. 给handleError加空值判断,避免无response时的报错
  4. 补全请求拦截器错误回调的return语句
  5. 可选优化:给请求加重试标记,避免refreshToken失效时进入无限401重试循环
核心代码修正示例

1. 修正injectToken函数

const injectToken = (config: AxiosRequestConfig): AxiosRequestConfig => {
  if (
    config.baseURL === API_HOST &&
    !config.headers.Authorization &&
    useAuthStatus.getState().status === "logged-in"
  ) {
    try {
      const token = getAccessToken();
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
    } catch (error) {
      throw new Error(error);
    }
  }
  // 所有分支都要返回config
  return config;
};

2. 修正请求拦截器错误回调

http.interceptors.request.use(injectToken, (error) => {
  // 补全return语句抛出错误
  return Promise.reject(error);
});

3. 修正响应拦截器错误回调

http.interceptors.response.use(
  (response) => {
    const { data } = response;
    return data;
  },
  (error) => {
    // 传入完整error对象,不要只传response
    return this.handleError(error);
  }
);

4. 修正handleError逻辑

private handleError(error: AxiosError) {
  // 先处理无响应的情况(网络错误、跨域等)
  if (!error.response) {
    return Promise.reject(error);
  }
  const { status } = error.response;
  // 从原始error对象上取请求配置
  const originalRequestConfig = error.config as AxiosRequestConfig & { isRetry?: boolean };

  switch (status) {
    case StatusCode.InternalServerError: {
      break;
    }
    case StatusCode.Forbidden: {
      // Handle Forbidden
      break;
    }
    case StatusCode.Unauthorized: {
      // 加重试标记避免死循环
      if (useAuthStatus.getState().status === "logged-in" && !originalRequestConfig.isRetry) {
        originalRequestConfig.isRetry = true;
        return refreshToken().then((_) => {
          originalRequestConfig.headers.Authorization = `Bearer ${useTokenStore.getState().accessToken}`;
          return this.request(originalRequestConfig);
        });
      }
      // 未登录或重试失败直接退出登录
      useAuthStatus.getState().logout();
      return Promise.reject(error);
    }
    case StatusCode.TooManyRequests: {
      // Handle TooManyRequests
      break;
    }
  }

  return Promise.reject(error);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 12:09:03