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

React中JWT刷新Token失败处理:避免未捕获错误

解决React JWT应用中Refresh Token失败后无错误跳转登录页的问题

问题根源

你遇到的核心问题是:即使执行了登录跳转,拦截器最后仍会执行return Promise.reject(err),导致上层组件的错误捕获机制(比如React ErrorBoundary)触发,显示未捕获错误页面。此外,多请求同时触发401时会重复调用刷新接口,也会引发额外错误。

修改方案

通过添加刷新锁、终止错误传递两个关键调整,实现无错误跳转:

import axios from "axios";
import TokenService from "./token";

const instance = axios.create({
    baseURL: process.env.REACT_APP_BACKEND_API_URL,
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
    },
    timeout: 5000
});

// 新增:标记是否正在刷新Token,防止多请求重复触发刷新
let isRefreshing = false;

instance.interceptors.request.use(
    (config) => {
        const token = TokenService.getLocalAccessToken();
        if (token) {
            config.headers['Authorization'] = 'Bearer ' + token;
        }
        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);

instance.interceptors.response.use(
    (res) => {
        return res;
    },
    async (err) => {
        const originalConfig = err.config;

        if (originalConfig.url !== "/login" && err.response) {
            if (err.response.status === 401 && !originalConfig.retry) {
                // 已有请求在刷新Token时,等待后重试当前请求
                if (isRefreshing) {
                    try {
                        await new Promise(resolve => setTimeout(resolve, 500));
                        return instance(originalConfig);
                    } catch (e) {
                        return Promise.reject(e);
                    }
                }

                originalConfig.retry = true;
                isRefreshing = true;

                try {
                    const response = await instance.post("/refreshtoken", {
                        "@ObjectType": "RefreshToken#1.0.0",
                        RefreshToken: TokenService.getLocalRefreshToken(),
                    });
                    TokenService.updateLocalAccessToken(response.data.Token);
                    TokenService.updateLocalRefreshToken(response.data.RefreshToken);
                    isRefreshing = false;
                    return instance(originalConfig);
                } catch (error) {
                    isRefreshing = false;
                    TokenService.removeUser();
                    window.location.replace(`${process.env.REACT_APP_FRONTEND_URL}/#/login`);
                    // 关键:返回已resolved的Promise,终止错误传递,避免上层捕获错误
                    return Promise.resolve();
                }
            }
        }

        // 非401刷新失败场景,正常抛出错误
        return Promise.reject(err);
    }
);

export default instance;

关键修改说明

  1. 刷新锁isRefreshing:避免多个请求同时触发Refresh Token接口,防止重复请求和状态冲突。
  2. catch块返回Promise.resolve():终止错误链,上层组件不会捕获到错误,也就不会触发未捕获错误页面。
  3. 等待重试逻辑:当已有请求在刷新Token时,其他请求等待短暂时间后重试,确保能使用新Token继续请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 18:55:05