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

React Native多API并行调用时Access Token刷新问题及崩溃修复

React Native Token 刷新问题解决方案

一、解决并行API重复刷新Token导致账号封禁问题

核心思路是用Promise缓存刷新请求,确保同一时间只有一个刷新Token的请求发送到后端,后续API请求等待该请求完成后复用结果。

实现步骤:

  1. 在全局 scope(比如API封装文件、状态管理模块)定义一个缓存刷新请求的Promise变量:
let refreshTokenPromise = null;
  1. 修改getNewToken函数,利用该Promise控制请求唯一性:
const getNewToken = async (refToken: string) => {
  // 已有刷新请求在处理时,直接返回该Promise的结果
  if (refreshTokenPromise) {
    return refreshTokenPromise;
  }

  let formattedEndpoint = ENDPOINT.LOGIN;
  let tokenVal = {};
  const header = { refresh_token: refToken };
  const requestQuery = {
    ...REFRESH_AUTH_HEADERS,
    ...header,
  };
  const queryParams = new URLSearchParams({
    ...requestQuery,
  }).toString();
  formattedEndpoint = `${formattedEndpoint}?${queryParams}`;

  // 将刷新请求赋值给全局Promise,后续请求复用
  refreshTokenPromise = api.post<LoginSuccess>(
    formattedEndpoint,
    {},
    {
      headers: basicAuthHeaders,
    }
  )
  .then(async refreshResponse => {
    if (refreshResponse.status === 200) {
      tokenVal = {
        access_token: refreshResponse.data?.access_token,
        refresh_token: refreshResponse.data?.refresh_token,
        expires_in: refreshResponse.data?.expires_in,
        type: 'private',
      };
    } else {
      tokenVal = {
        access_token: null,
        token_type: null,
        refresh_token: null,
        expires_in: null,
        scope: null,
        id_token: null,
        type: 'public',
      };
      tokenVal = await refreshPublicToken();
    }
    return tokenVal;
  })
  .catch(async error => {
    // 统一处理刷新失败的情况
    tokenVal = await refreshPublicToken();
    return Promise.reject(error);
  })
  .finally(() => {
    // 请求完成后清空Promise,允许下次刷新
    refreshTokenPromise = null;
  });

  return refreshTokenPromise;
};

二、解决多次调用logout()导致应用崩溃问题

通过状态标志位控制登出和页面跳转操作只执行一次,避免重复触发。

实现步骤:

  1. 在状态管理(比如Redux、Context)中添加isLoggingOut状态,标记是否正在执行登出流程:
// 以Redux Slice为例
const authSlice = createSlice({
  name: 'auth',
  initialState: {
    // ...其他状态
    isLoggingOut: false,
  },
  reducers: {
    setIsLoggingOut: (state, action) => {
      state.isLoggingOut = action.payload;
    },
    // ...其他reducer
  },
});

export const { setIsLoggingOut } = authSlice.actions;
  1. 修改logout action,添加状态判断避免重复执行:
export const logout = () => (dispatch, getState) => {
  const { isLoggingOut } = getState().auth;
  if (isLoggingOut) return;

  dispatch(setIsLoggingOut(true));
  // 执行登出逻辑:清除Token、重置状态等
  dispatch(setToken(null));
  // ...其他登出操作
};
  1. 在getNewToken和handleResponse的错误分支中,先判断状态再执行登出和跳转:
  • 修改getNewToken的错误分支:
else {
  const { isLoggingOut } = getState().auth;
  if (!isLoggingOut) {
    dispatch(logout());
    navigation.dispatch(StackActions.replace(NAVIGATION_SCREENS.ROOT));
  }
  tokenVal = {
    access_token: null,
    token_type: null,
    refresh_token: null,
    expires_in: null,
    scope: null,
    id_token: null,
    type: 'public',
  };
  tokenVal = await refreshPublicToken();
}
  • 修改handleResponse的无效Token分支:
else {
  const { isLoggingOut } = getState().auth;
  if (!isLoggingOut) {
    setInvalidToken(true);
    navigation.dispatch(StackActions.replace(NAVIGATION_SCREENS.ROOT));
  }
  return;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 15:53:13