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

React Native中Axios刷新Token后无法重新发起请求问题求助

问题描述
  • 在React Native中使用Axios发起携带accessToken的请求创建用户信息,已创建axiosInstance并在请求头设置Authorization字段为accessToken
  • accessToken未过期时请求正常;返回401(token过期)后,能成功重新获取accessToken,但刷新后无法重新发起请求
  • 已尝试方案:
    • 更换Axios版本至v1.6.8
    • 创建单例Promise确保仅发起一次刷新请求

用户提供的代码:

import axios from 'axios';
import EncryptedStorage from 'react-native-encrypted-storage';

const baseURL = '-';
const axiosInstance = axios.create({ baseURL });

let _refreshingPromise = null;

const reissueToken = async () => {
    try {
        const refreshToken = await EncryptedStorage.getItem('refreshToken');

        if (!refreshToken) {
            throw new Error("refreshToken doesnt exist");
        }

        const response = await axios.post(`${baseURL}/auth/renew`, { refreshToken });

        const newAccessToken = response.data.accessToken;
        await EncryptedStorage.setItem('accessToken', newAccessToken);

        return newAccessToken;
    } catch (error) {
        console.error("reissue failed ", error);
        throw error;
    }
};

axiosInstance.interceptors.request.use(
    async (config) => {
        try {
            const accessToken = await EncryptedStorage.getItem('accessToken');
            config.headers['Content-Type'] = 'application/json';
            config.headers['Authorization'] = accessToken;

            console.log("original requests config:", config);
            return config;
        } catch (error) {
            console.error("request interceptor failed:", error);
            return Promise.reject(error);
        }
    },
    (error) => {
        console.error("request interceptor error :", error);
        return Promise.reject(error);
    }
);


axiosInstance.interceptors.response.use(
    (response) => {
        console.log("request succeed!");
        return response;
    },
    async (error) => {
        const { config,response } = error;
        const status = response? response.status : null;

    
        console.log("response status code : ", status);
        if(status === 502) {
            console.log("502 error");
            
        }
        if (status === 401) {
            console.log("start!");
            if (!_refreshingPromise) {
                console.log(_refreshingPromise);
                _refreshingPromise = new Promise((resolve, reject) => {
                    reissueToken()
                        .then((newAccessToken) => {
                            console.log("newToken : ", newAccessToken);
                            config.headers['Authorization'] = newAccessToken;
                            console.log(config.headers.Authorization);

                            axios(config)
                            .then((response) => {
                                
                                console.log("response:", response.data);
                                resolve(response); 
                            })
                            .catch((error) => {
                                console.log("request failed!");
                                reject(error); 
                            })
                            .finally(() => {
                                _refreshingPromise = null;
                            });
                        })
                        .catch((reissueError) => {
                            reject(new Error('error', reissueError));
                        })
                        .finally(() => {
                            _refreshingPromise = null;
                        });
                });
            }

            return _refreshingPromise;
        }

        return Promise.reject(error);
    }
);

export default axiosInstance;
问题分析与修复方案

你的代码存在几个关键问题,导致刷新token后无法重新发起请求,以下是修复后的代码及说明:

修复后代码

import axios from 'axios';
import EncryptedStorage from 'react-native-encrypted-storage';

const baseURL = '-';
const axiosInstance = axios.create({ baseURL });

let _refreshingPromise = null;

const reissueToken = async () => {
    try {
        const refreshToken = await EncryptedStorage.getItem('refreshToken');

        if (!refreshToken) {
            throw new Error("refreshToken doesnt exist");
        }

        const response = await axios.post(`${baseURL}/auth/renew`, { refreshToken });

        const newAccessToken = response.data.accessToken;
        await EncryptedStorage.setItem('accessToken', newAccessToken);

        return newAccessToken;
    } catch (error) {
        console.error("reissue failed ", error);
        throw error;
    }
};

axiosInstance.interceptors.request.use(
    async (config) => {
        try {
            // 跳过刷新token的请求,避免不必要的token获取逻辑
            if (config.url.includes('/auth/renew')) {
                return config;
            }
            
            const accessToken = await EncryptedStorage.getItem('accessToken');
            config.headers['Content-Type'] = 'application/json';
            if (accessToken) {
                config.headers['Authorization'] = accessToken;
            }

            console.log("original requests config:", config);
            return config;
        } catch (error) {
            console.error("request interceptor failed:", error);
            return Promise.reject(error);
        }
    },
    (error) => {
        console.error("request interceptor error :", error);
        return Promise.reject(error);
    }
);


axiosInstance.interceptors.response.use(
    (response) => {
        console.log("request succeed!");
        return response;
    },
    async (error) => {
        const { config, response } = error;
        const status = response ? response.status : null;

        console.log("response status code : ", status);
        if (status === 502) {
            console.log("502 error");
        }

        // 仅处理未标记为重试的401请求,避免循环触发刷新逻辑
        if (status === 401 && !config._retry) {
            console.log("start!");
            if (!_refreshingPromise) {
                _refreshingPromise = reissueToken()
                    .then((newAccessToken) => {
                        console.log("newToken : ", newAccessToken);
                        // 标记请求为重试,防止再次进入401拦截逻辑
                        config._retry = true;
                        config.headers['Authorization'] = newAccessToken;
                        console.log(config.headers.Authorization);

                        // 使用axiosInstance重发请求,复用已配置的拦截器和基础设置
                        return axiosInstance(config);
                    })
                    .catch((reissueError) => {
                        console.error("reissue and retry failed:", reissueError);
                        throw reissueError;
                    })
                    .finally(() => {
                        // 统一清空刷新Promise,避免后续请求阻塞
                        _refreshingPromise = null;
                    });
            }

            return _refreshingPromise;
        }

        return Promise.reject(error);
    }
);

export default axiosInstance;

关键修改点

  1. 改用axiosInstance重发请求:原代码用全局axios(config)发起重发请求,没有复用你配置的axiosInstance的拦截器和基础设置,改为axiosInstance(config)后能正确走已有的请求逻辑。
  2. 添加重试标记避免循环:给config添加_retry属性,确保401请求仅触发一次刷新逻辑,不会因为重发请求再次进入响应拦截器的401分支。
  3. 简化刷新Promise逻辑:去掉嵌套的Promise创建,直接返回reissueToken的Promise链,避免异步逻辑混乱,同时统一在finally中清空_refreshingPromise,防止重复置空导致的问题。
  4. 跳过刷新请求的拦截器处理:在请求拦截器中判断如果是刷新token的请求,直接返回config,避免不必要的accessToken获取操作。

内容的提问来源于stack exchange,提问作者김민지

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:43:10