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;
自留