vue3 前端 Token无痛刷新

1.token过期需要解决的几个痛点

1.1怎么在响应式拦截器中重新发起请求
1.2怎么处理token过期后大量请求并发
1.3token过期后在响应拦截器中怎么重新获取token

import axios from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Session } from '/@/utils/storage';
import { refreshToken } from '/@/api/login/logg.js';
import { useStore } from '/@/store/index';
// 配置新建一个 axios 实例

// 获取token失效效时间
const token_time = Session.get('token_time')
// 获取用户信息
const userInfo = Session.get('userInfo') || ''

/*被挂起的请求数组*/
let refreshSubscribers = [];
const subscribeTokenRefresh = (cb:Function) => {
	refreshSubscribers.push(cb);
	console.log(refreshSubscribers,'挂起的数组');
	
}
/*刷新请求(refreshSubscribers数组中的请求得到新的token之后会自执行,用新的token去请求数据)*/
function onRrefreshed(token) {
	
	refreshSubscribers.map(cb => {
		cb(token)
	});		
  }

const service = axios.create({
	baseURL: import.meta.env.VITE_API_URL,
	timeout: 50000, //超时时间
	headers: { 'Content-Type': 'application/json' },
});



// 添加请求拦截器
service.interceptors.request.use(
	(config) => {
		
		// 在发送请求之前做些什么 token
		if (Session.get('token')) {
			
			//如果有token自动添加到请求头
			config.headers.common['Authorization'] = `Bearer ${Session.get('token')}`;
			if (Session.get('tenant_id')) {
				config.headers['TENANT-ID'] = `${Session.get('tenant_id')}`;
			}
		}
		return config;
	},
	(error) => {
		// 对请求错误做些什么
		return Promise.reject(error);
	}
);



// 添加响应拦截器
service.interceptors.response.use(
	(response) => {
		// 对响应数据做点什么
		const res = response.data;
		 /*将请求挂起*/

		
		if (res.code && res.code !== 0) {
			// `token` 过期或者账号已在别处登录
			if (res.code === 401 || res.code === 4001) {
				Session.clear(); // 清除浏览器全部临时缓存
				window.location.href = '/'; // 去登录页
				ElMessageBox.alert('您已被登出,请重新登录', '提示', {})
					.then(() => {})
					.catch(() => {});
				
			}
			
			
			
			return Promise.reject(service.interceptors.response);
		} else {
			
			
			return response.data;
		}
	},
	 (error) => {
		// var reg=new RegExp('"',"g"); //创建正则RegExp对象
		const refresh_token =  Session.get('refresh_token')
		console.log(refresh_token);
		
		// 对响应错误做点什么
		function reloadMessage (config) {
			console.log(config);
			
			refreshToken(refresh_token).then(res =>{
				console.log(res);

				var tempdate = Date.now()
				console.log(`更新token时的当前时间${tempdate};\n新的token${res?.access_token}`)
				/*成功刷新token*/
				config.headers['Authorization'] =  `Bearer ${res?.access_token}`
				// 清除本地token
				/*更新本地的token*/
				Session.set('token',res?.access_token)
				Session.set('refresh_token',res?.refresh_token)
				/*执行数组里的函数,重新发起被挂起的请求*/
				onRrefreshed(res?.access_token)
				/*执行onRefreshed函数后清空数组中保存的请求*/
				refreshSubscribers = []
			})
			/*将请求挂起*/
			let retry = new Promise((resolve, reject) => {
				
				/*(token) => {...}这个函数就是回调函数*/
				subscribeTokenRefresh(token => { `	 `
					console.log("重发token is", token.substr(-4));
					config.headers["Authorization"] = `Bearer ${token}`;
					console.log(config.headers["Authorization"],'替换的headersToken');
					
					axios.request(config).then(res =>{
						console.log(res);
						// window.requestCount = 0
						resolve(res.data)
					})
				});
				});
				return retry;
		}
		if (error.message.indexOf('timeout') != -1) {
			ElMessage.error('网络超时');
		} else if (error.message == 'Network Error') {
			ElMessage.error('网络连接错误');
		} else {
			// if (error.response.data) ElMessage.error(error.response.data.msg)
			// else ElMessage.error('接口路径找不到');
			if (error.response.data) {
				if (error.response.data instanceof Blob) return;
				// ElMessage.error(error.response.data.msg || '接口路径找不到');
				// 424 token过期
				if (error.response.data.msg == 'token 过期') {
					if(Date.now() - userInfo.time >= token_time ){
						return reloadMessage(error.config)
					}
					
					// Session.clear(); // 清除浏览器全部临时缓存
					// window.location.href = '/'; // 去登录页
					// ElMessageBox.alert('您已被登出,请重新登录', '提示', {})
					// 	.then(() => {})
					// 	.catch(() => {});
				}
			}
		}

		
		return Promise.reject(error);
	}
	
	
);

// 导出 axios 实例
export default service;

自留

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值