如何复用Token至过期后再重新获取?(JS/TS实现)
解决Axios拦截器重复获取Token导致429错误的方案
问题现状
当前axios请求拦截器中,每次发起请求都会调用LoginAPI.API.Signin.run()获取Token,导致短时间内大量请求触发429(请求过于频繁)错误。需要实现Token复用机制:仅在Token不存在或已过期时,才重新请求新Token,避免重复调用登录接口。
代码改造步骤
1. 扩展LoginAPI,增加Token过期时间管理
修改Login.e2e.ts,新增Token过期时间状态,并在登录成功后计算过期时间(假设登录接口返回的res.data包含expires_in字段,单位为秒):
import api from "api/core" import { expect } from "@playwright/test"; export const LoginAPI = { States: { token: "" as string, expiresAt: 0 as number // 存储Token过期时间戳(毫秒) }, API: { Signin: { notes: "user login", run: async () => { const res: any = await api.test.LoginPost(process.env.NAME, process.env.PASS) LoginAPI.States.token = res.data.token // 计算过期时间:当前时间 + expires_in秒(转毫秒) LoginAPI.States.expiresAt = Date.now() + (res.data.expires_in * 1000) expect(res.status).toBe(200) }, }, }, // 判断Token是否有效(存在且未过期) isTokenValid(): boolean { return !!LoginAPI.States.token && Date.now() < LoginAPI.States.expiresAt } };
2. 改造Axios拦截器,实现Token复用与并发控制
修改axios.ts,添加并发请求锁(避免多个请求同时触发登录),仅在Token无效时才调用登录接口:
import axios from "axios"; import { LoginAPI } from "../playwright/tests/login/login.api"; const customAxios = axios.create({ baseURL: process.env.ENV === '1' ? "https://test1" : process.env.ENV === '2' ? "https://test2" : "https://test3", }); // 全局登录Promise,用于并发请求时避免重复登录 let loginPromise: Promise<void> | null = null; customAxios.interceptors.request.use( async (config) => { // 1. 检查Token是否有效 if (!LoginAPI.isTokenValid()) { // 2. 若已有登录请求在进行,直接复用该Promise if (!loginPromise) { loginPromise = LoginAPI.API.Signin.run().finally(() => { // 登录完成后清空Promise锁 loginPromise = null; }); } await loginPromise; } // 3. 给请求头添加Token if (config.headers) { config.headers['Authorization'] = `Bearer ${LoginAPI.States.token}`; } return config; }, (error) => { return Promise.reject(error); } ); export default customAxios
关键逻辑说明
- Token有效性判断:通过
isTokenValid()方法检查Token是否存在且未到过期时间,避免无效Token被使用。 - 并发请求控制:使用
loginPromise锁,当多个请求同时发现Token过期时,只会发起一次登录请求,其余请求等待该Promise完成后复用新Token,彻底避免重复登录导致的429错误。 - 过期时间计算:基于登录接口返回的
expires_in计算过期时间戳,确保Token在有效期内被复用,过期后自动触发重新登录。
内容的提问来源于stack exchange,提问作者YusufOzt
相关产品推荐
相关产品推荐

