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

React Native中Axios刷新Access Token后仍报401错误求助

问题:Access Token过期后刷新Token仍无法获取分类数据

当前代码在Access Token未过期时能正常获取分类数据,但当Access Token过期触发401错误后,调用刷新Token函数更新Access和Refresh Token后,仍然返回[AxiosError: Request failed with status code 401]错误,以下是相关代码及问题分析:

相关代码

1. 刷新Token函数

export async function refreshTokenGenerator() {
  const url = RefreshCurrentTokenURL;
  const refreshTokenGeneratedFirst = newUser.getRefreshToken();
  const response = await axios
    .post(url, {
      refreshToken: refreshTokenGeneratedFirst,
    })
    .catch((error) => {
      console.log(
        "🚀 ~ file: auth.js:118 ~ refreshTokenGenerator ~ error cant refresh token",
        error
      );
    });
  const newRefreshTokenGenerated = response.data.refreshToken;
  // 将新生成的Refresh Token赋值给用户模型
  // Refresh Token循环正常,覆盖RT无错误
  const assignNewRefreshTokenToUserModel = newUser.setRefreshToken(
    newRefreshTokenGenerated
  );
  // Access Token循环正常
  // 当收到401错误时调用,因为这代表AT已过期
  const newAccessTokenGenerated = response.data.token;
  return newAccessTokenGenerated;
}

2. 更新AccessToken函数

export async function updateAccessToken() {
  console.log("updateAccessToken called");
  const newGeneratedTokenAfterExpiration = await refreshTokenGenerator();
  newUser.setToken(newGeneratedTokenAfterExpiration);
  const userToken = newGeneratedTokenAfterExpiration;
  return userToken;
}

3. 菜单认证与获取分类函数

async function authenticateMenu() {
  const url = CategoriesAuthUrl;
  let userToken = newUser.getToken();
  const authStr = "Bearer ".concat(userToken);
  const options = {
    method: "GET",
    headers: {
      Authorization: authStr,
    },
    url: url,
  };
  const response = await axios(options).catch(async (error) => {
    if (error.response.status === 401) {
      // 应调用刷新Token的函数来更新Access和Refresh Token
      console.log("Error 401 unauthorized");
      const newUserToken = await updateAccessToken();
      userToken = newUserToken;
    }
    console.log(
      "😡 ~ file: menu.js:28 ~ authenticateMenu ~ Error getting categories from API call",
      error
    );
  });
  const fetchedCategories = response.data;
  console.log(
    "🚀 ~ file: menu.js:40 ~ authenticateMenu ~ fetchedCategories",
    fetchedCategories
  );
  return fetchedCategories;
}

// 获取分类
export async function getCategories() {
  return authenticateMenu();
}

4. HomeScreen调用代码

useEffect(() => {
  async function fetchCatHandler() {
    const categoriesFetched = await getCategories().catch((error) => {
      console.log(
        "🟥 ~ file: HomeScreen.js:63 ~ fetchCatHandler ~ error from fetching categories from Home screen",
        error
      );
    });
    setParsedCategories(categoriesFetched);
  }
  fetchCatHandler();
  async function getUserName() {
    setUserName(await newUser.getUserName());
  }
  getUserName();
}, []);

问题分析与解决方案

核心问题

  1. 未重新发起请求:在authenticateMenu的catch块中,仅更新了userToken但未用新Token重新发送请求,原请求已失败,response仍处于错误状态或为undefined,后续读取response.data会直接报错。
  2. 刷新Token函数未处理请求失败场景:refreshTokenGenerator中若axios请求失败,catch仅打印日志无返回值,导致response为undefined,后续读取response.data会抛出错误。

修复方案

方案1:修复authenticateMenu函数,刷新Token后重新请求

修改函数逻辑,在刷新Token后用新Token重新发起请求:

async function authenticateMenu() {
  const url = CategoriesAuthUrl;
  let userToken = newUser.getToken();
  try {
    const authStr = "Bearer ".concat(userToken);
    const response = await axios({
      method: "GET",
      headers: { Authorization: authStr },
      url: url,
    });
    return response.data;
  } catch (error) {
    if (error.response?.status === 401) {
      console.log("Error 401 unauthorized, refreshing token...");
      // 刷新Token
      const newUserToken = await updateAccessToken();
      // 用新Token重新发起请求
      const newAuthStr = "Bearer ".concat(newUserToken);
      const response = await axios({
        method: "GET",
        headers: { Authorization: newAuthStr },
        url: url,
      });
      return response.data;
    }
    console.log("😡 ~ file: menu.js:28 ~ authenticateMenu ~ Error getting categories from API call", error);
    throw error; // 抛出错误让上层处理
  }
}

方案2:完善refreshTokenGenerator的错误处理

避免请求失败时response为undefined导致后续报错:

export async function refreshTokenGenerator() {
  const url = RefreshCurrentTokenURL;
  const refreshTokenGeneratedFirst = newUser.getRefreshToken();
  try {
    const response = await axios.post(url, {
      refreshToken: refreshTokenGeneratedFirst,
    });
    const newRefreshTokenGenerated = response.data.refreshToken;
    newUser.setRefreshToken(newRefreshTokenGenerated);
    const newAccessTokenGenerated = response.data.token;
    return newAccessTokenGenerated;
  } catch (error) {
    console.log("🚀 ~ file: auth.js:118 ~ refreshTokenGenerator ~ error cant refresh token", error);
    throw error; // 抛出错误让上层处理,比如跳转登录页
  }
}

方案3:推荐使用Axios拦截器统一处理Token刷新(更优雅)

设置全局响应拦截器,统一处理401错误,无需在每个请求中重复写逻辑:

// 创建Axios实例
const api = axios.create({ baseURL: '你的API基础地址' });

// 请求拦截器:自动添加Token
api.interceptors.request.use(
  (config) => {
    const token = newUser.getToken();
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器:处理401刷新Token
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    const originalRequest = error.config;
    // 避免重复刷新Token
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        const newToken = await refreshTokenGenerator();
        newUser.setToken(newToken);
        originalRequest.headers.Authorization = `Bearer ${newToken}`;
        // 重新发起原请求
        return api(originalRequest);
      } catch (refreshError) {
        // 刷新Token失败,跳转到登录页
        console.log("Refresh token failed, redirect to login");
        // 这里添加跳转登录的逻辑,比如navigation.navigate('Login')
        return Promise.reject(refreshError);
      }
    }
    return Promise.reject(error);
  }
);

// 之后使用api实例发起请求
async function authenticateMenu() {
  const response = await api.get(CategoriesAuthUrl);
  return response.data;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:40:19