当前位置: 首页 > news >正文

一个项目中调用两个不同后台,前端如何优雅实现无感刷新Token调用接口

文章目录

    • 需求
    • 分析
    • 解决
      • 1. 配置多个代理地址
      • 2. 在之前的拦截器外再写一套针对该问题的拦截器

需求

在一个项目中需要调用另一个项目的接口,但另一个项目中的接口在调用时需要先登录获取到token,才能调用该接口,应该如何做呢?

分析

自动处理流程:

  1. 每次请求前检查 token 是否存在或过期
  2. token 无效时自动调用登录接口获取新 token
  3. 401 错误时自动刷新 token 并重试请求
  4. 并发请求会等待 token 刷新完成后再执行

解决

  1. 对新加的代理地址单独做一套请求
  2. 在请求时判断是否有登录信息,如果没有或 token 过期,则先调用登录接口存储 token 信息
  3. 在接下来的接口中就可以正常调用了

1. 配置多个代理地址

proxy: {'/prod-api': {target: "http://地址1", //请求的地址changeOrigin: false,rewrite: (path) => path.replace(/^\/prod-api/, '/prod-api'),},'/dev-api': {target: 'http://地址2',changeOrigin: true,rewrite: (path) => path.replace(/^\/dev-api/, '/dev-api'),},
}

2. 在之前的拦截器外再写一套针对该问题的拦截器

新建request.js

import axios from 'axios';// 创建 axios 实例
const service = axios.create({timeout: 10000,
});// 存储 token 信息
let tokenInfo = {token: localStorage.getItem('video_token') || null,expiresAt: localStorage.getItem('video_token_expires_at')? new Date(localStorage.getItem('video_token_expires_at')): null
};// 请求拦截器 - 在每次请求前检查 token
service.interceptors.request.use(async (config) => {// 检查是否需要 token(根据实际项目调整)if (needToken(config.url)) {// 检查 token 是否存在或已过期if (!tokenInfo.token || isTokenExpired()) {await refreshToken();}// 设置 token 到请求头config.headers['access-token'] = `${tokenInfo.token}`}return config;},(error) => {console.error('请求拦截器错误:', error);return Promise.reject(error);}
);// 响应拦截器 - 处理 401 错误
service.interceptors.response.use((response) => {return response;},async (error) => {const originalRequest = error.config;// 处理 401 错误(token 过期)if (error.response?.status === 401 && !originalRequest._retry) {originalRequest._retry = true;try {// 刷新 tokenawait refreshToken();// 重试原请求originalRequest.headers['access-token'] = `${tokenInfo.token}`return service(originalRequest);} catch (refreshError) {console.error('刷新 token 失败:', refreshError);// 跳转到登录页或执行其他操作return Promise.reject(refreshError);}}return Promise.reject(error);}
);// 判断请求是否需要 token
function needToken (url) {// 排除登录接口return !url.includes('/login');
}// 检查 token 是否过期
function isTokenExpired () {return !tokenInfo.expiresAt || new Date() >= tokenInfo.expiresAt;
}// 刷新 token
async function refreshToken () {// 如果正在刷新 token,等待刷新完成if (window.isRefreshingToken) {return new Promise((resolve) => {const waitInterval = setInterval(() => {if (!window.isRefreshingToken) {clearInterval(waitInterval);resolve(tokenInfo.token);}}, 100);});}window.isRefreshingToken = true;try {// 调用登录接口获取新 tokenconst response = await axios.get('/dev-api/api/user/login?username=admin&password=21232f297a57a5a743894a0e4a801fc3');// 提取 token 和过期时间(根据实际接口返回调整)tokenInfo.token = response.data.accessToken;// 假设返回中包含 expiresIn(秒)const expiresIn = response.data.expiresIn || 3600;tokenInfo.expiresAt = new Date(Date.now() + expiresIn * 1000);// 存储到本地存储localStorage.setItem('video_token', tokenInfo.token);localStorage.setItem('video_token_expires_at', tokenInfo.expiresAt.toString());return tokenInfo.token;} catch (error) {console.error('获取 token 失败:', error);// 清除无效 tokentokenInfo = { token: null, expiresAt: null };localStorage.removeItem('video_token');localStorage.removeItem('video_token_expires_at');throw error;} finally {window.isRefreshingToken = false;}
}// 导出配置好的 axios 实例
export default service;
  1. 接口调用
import request from './request.js'
export function auxiliary([deviceId, channelDeviceId, command, switchId]) {return request({method: 'get',url: `/dev-api/api/front-end/auxiliary/${deviceId}/${channelDeviceId}`,params: {command: command,switchId: switchId}})
}
http://www.lryc.cn/news/575119.html

相关文章:

  • webpack5 css-loader:从基础到原理
  • css实现a标签前面加小图标
  • 【GStreamer】减小延时的参数设置、从RTP中获取时间戳
  • 深入探索WordPress Multisite:构建与管理多站点网络
  • 【Lua 基础学习】
  • C++(智能指针)
  • LeetCode 3298.统计重新排列后包含另一个字符串的子字符串数目2
  • ivx创建一个测试小案例
  • Vue3插槽
  • 基于springboot+vue的智慧农业专家远程指导系统
  • 批量DWG转PDF工具
  • ES和 Kafka 集群搭建过程中的典型问题、配置规范及最佳实践
  • RK平台HDMI-IN/camera调试:预留CMA内存
  • Mac安装Apache CXF的时候报错:/Library/Internet: No such file or directory
  • 打造属于你的AI智能体,从数据开始 —— 使用 Bright Data MCP+Trae快速构建垂直智能体
  • 操作系统之内存管理(王道)
  • Azure 自动化:所需状态配置 (DSC)
  • UniApp 开发第一个项目
  • Python虚拟环境管理:conda、venv、pipenv三国杀
  • JSON框架转化isSuccess()为sucess字段
  • Fisco Bcos学习 - 开发第一个区块链应用
  • PAC 学习框架:机器学习的可靠性工程
  • 通俗易懂解读BPE分词算法实现
  • 回归预测 | Matlab实现KAN神经网络多输入单输出回归预测模型
  • 轻巧灵动,智启未来 ——Kinova Gen3 Lite 机器人轻松解锁各行业自动化新姿势
  • 领域驱动设计(DDD)【13】之重构中的坏味道:深入理解依恋特性(Feature Envy)与表意接口模式
  • 香港电讯携手Palo Alto Networks,护航企业跨区域数字化之旅
  • 第8章项目进度管理归纳总结补充
  • 英飞凌高性能BMS解决方案助力汽车电动化
  • python学智能算法(十六)|机器学习支持向量机简单示例