You need to enable JavaScript to run this app. React Native中使用Axios如何在JWT过期刷新后重发原请求
优惠活动
大模型
产品
解决方案
定价
更多

React Native中使用Axios如何在JWT过期刷新后重发原请求

Axios 刷新JWT后重发原请求的实现方案

核心逻辑说明

你已经完成的token过期校验、refreshToken调用逻辑都可以和Axios的拦截器机制结合,重发原请求的核心是复用请求拦截器/响应拦截器中拿到的原始请求配置对象,更新Authorization头后直接用Axios实例重新调用该配置即可。
同时需要加刷新状态锁和请求队列,避免并发场景下重复调用refreshToken接口。


完整代码实现

前置变量声明

// 标记当前是否正在刷新token,避免重复发起刷新请求
let isRefreshing = false
// 存储刷新token过程中积压的请求回调队列
let requestQueue = []

1. 适配你已有的「请求前校验token过期」逻辑的方案

你可以直接在请求拦截器中完成过期校验+刷新+重发的全流程:

import axios from 'axios'
// 替换为你自己项目里的token存取、校验工具,比如用@react-native-async-storage/async-storage做存储
import { getAccessToken, getRefreshToken, saveAccessToken, isTokenExpired, clearToken } from './authUtils'
// 替换为你自己的路由实例,用于refresh失败时跳登录
import navigation from './navigationRef'

// 初始化自定义Axios实例
const apiClient = axios.create({
  baseURL: '你的接口根地址',
  timeout: 15000
})

// 请求拦截器
apiClient.interceptors.request.use(
  async (config) => {
    const accessToken = getAccessToken()
    // 统一给请求加Authorization头
    if (accessToken) {
      config.headers.Authorization = `Bearer ${accessToken}`
    }

    // 你已有的token过期校验逻辑
    const expired = isTokenExpired(accessToken)
    if (!expired) return config

    // 走到这里说明token已过期
    if (!isRefreshing) {
      isRefreshing = true
      try {
        // 调用你已有的refreshToken接口,传入refreshToken拿新的accessToken
        const newAccessToken = await refreshTokenRequest(getRefreshToken())
        // 保存新token到本地
        saveAccessToken(newAccessToken)
        // 更新当前请求的头信息
        config.headers.Authorization = `Bearer ${newAccessToken}`

        // 执行队列中积压的所有请求,传入新token
        requestQueue.forEach(cb => cb(newAccessToken))
        requestQueue = []

        // 直接返回更新后的配置,Axios会自动重发当前请求
        return config
      } catch (err) {
        // refreshToken也过期/失效,清空本地token跳登录页
        clearToken()
        navigation.navigate('Login')
        return Promise.reject(err)
      } finally {
        isRefreshing = false
      }
    } else {
      // 已经在刷新token了,把当前请求加入队列,等刷新完成后再执行
      return new Promise(resolve => {
        requestQueue.push(newToken => {
          config.headers.Authorization = `Bearer ${newToken}`
          resolve(config)
        })
      })
    }
  },
  error => Promise.reject(error)
)

export default apiClient

2. 补充:响应拦截器捕获401错误的适配方案

如果存在token未到过期时间但提前失效(比如被后端吊销、篡改)的场景,可以加响应拦截器兜底,核心重发逻辑如下:

apiClient.interceptors.response.use(
  res => res,
  async error => {
    const originalRequest = error.config
    // 仅处理401错误、且不是重发的请求,避免死循环
    if (error.response?.status === 401 && !originalRequest._retry) {
      if (isRefreshing) {
        // 刷新中,把请求加入队列
        return new Promise(resolve => {
          requestQueue.push(newToken => {
            originalRequest.headers.Authorization = `Bearer ${newToken}`
            originalRequest._retry = true
            resolve(apiClient(originalRequest))
          })
        })
      }

      originalRequest._retry = true
      isRefreshing = true
      try {
        const newAccessToken = await refreshTokenRequest(getRefreshToken())
        saveAccessToken(newAccessToken)
        originalRequest.headers.Authorization = `Bearer ${newAccessToken}`
        // 执行队列请求
        requestQueue.forEach(cb => cb(newAccessToken))
        requestQueue = []
        // 核心重发逻辑:传入原请求配置重新调用Axios实例
        return apiClient(originalRequest)
      } catch (err) {
        clearToken()
        navigation.navigate('Login')
        return Promise.reject(err)
      } finally {
        isRefreshing = false
      }
    }
    return Promise.reject(error)
  }
)

注意事项

  • 给原请求配置加_retry标记是为了避免重发的请求再次401时进入无限循环
  • 请求队列可以解决同时发起多个请求时,重复调用refreshToken接口的问题
  • React Native环境下注意处理refreshToken调用时的网络错误、本地存储读写异常的边界情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 09:15:08