token无感刷新

在前端应用中,常常需要处理因token过期而导致的请求失败的情况。我们可以将这些失败的请求挂起,待token刷新成功后重试这些请求。以下是一个实现细节:

基本思路

  1. 拦截请求失败: 使用请求库(如Axios)拦截请求错误,判断是否因token过期而失败。
  2. 存储挂起请求: 将这些请求存储在一个数组中,以便在token刷新成功后重试。
  3. 刷新token: 当检测到token过期时,触发刷新token的请求。
  4. 重试挂起请求: 在token刷新成功后,重新发送挂起的请求。

实现步骤

以下是一个使用Axios的示例:

import axios from 'axios';

// 创建一个Axios实例
const apiClient = axios.create();

// 挂起请求的数组
let pendingRequests = [];

// 是否正在刷新token
let isRefreshing = false;

// 请求拦截器,添加token到请求头
apiClient.interceptors.request.use(config => {
    const token = localStorage.getItem('access_token');
    if (token) {
        config.headers['Authorization'] = `Bearer ${token}`;
    }
    return config;
}, error => {
    return Promise.reject(error);
});

// 响应拦截器,处理token过期
apiClient.interceptors.response.use(response => {
    return response;
}, error => {
    const { config, response } = error;
    const originalRequest = config;

    // 检查是否是token过期错误(假设401表示过期)
    if (response && response.status === 401) {

        // 如果已经在刷新token,将请求挂起
        if (isRefreshing) {
            return new Promise((resolve, reject) => {
                pendingRequests.push({ resolve, reject });
            }).then(token => {
                originalRequest.headers['Authorization'] = `Bearer ${token}`;
                return axios(originalRequest);
            }).catch(err => {
                return Promise.reject(err);
            });
        }

        // 开始刷新token
        isRefreshing = true;

        return new Promise((resolve, reject) => {
            refreshToken()  // 假设一个刷新token的方法
                .then(newToken => {
                    localStorage.setItem('access_token', newToken);
                    apiClient.defaults.headers['Authorization'] = `Bearer ${newToken}`;
                    originalRequest.headers['Authorization'] = `Bearer ${newToken}`;

                    // 重新发送所有挂起的请求
                    pendingRequests.forEach(req => {
                        req.resolve(newToken);
                    });

                    pendingRequests = [];
                    resolve(axios(originalRequest));
                })
                .catch(err => {
                    pendingRequests.forEach(req => {
                        req.reject(err);
                    });

                    pendingRequests = [];
                    reject(err);
                })
                .finally(() => {
                    isRefreshing = false;
                });
        });
    }

    return Promise.reject(error);
});

// 模拟刷新token的函数
function refreshToken() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const newToken = 'new-token-value';  // 假设获得了新token
            resolve(newToken);
        }, 1000);
    });
}

说明

  • 挂起请求: 当检测到token过期,且当前正在刷新token时,将请求存储在pendingRequests数组中。
  • 刷新token过程: 当刷新token成功后,遍历pendingRequests数组,使用新的token重试请求。
  • 状态管理: 使用isRefreshing标志来避免同时发起多个token刷新请求。

这个实现确保了API请求在token过期时不会被丢弃,而是等待token刷新后继续执行。根据实际需求,你可能需要调整token存储和获取的方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值