业务场景
前提:统一登录sso,双token:token,rToken
token过期时多次发出刷新Token请求,导致服务资源的浪费,所以我们需要添加一个标识isRefreshToken
解决多次刷新的问题后,发现刷新等待期间发出的请求仍然用的之前的Token导致报错,所以这里需要一个存储请求的数组refreshRequest
- request.js
// 请求前拦截(根据各个系统不同,请求头不同)
service.interceptors.request.use(
(config) => {
config.headers['Authorization'] = getToken()
config.headers['P-Rtoken'] = getRToken()
return config
},
(error) => {
return Promise.reject(error)
}
)
let isRefreshToken=false //是否正在刷新Token【防止多次刷新浪费资源】
let refreshRequest=[] // 缓存请求队列【解决刷新期间发出的请求任然报错问题】
// 返回结果前拦截
service.interceptors.response.use((response) => {
const res = response.data
// 如果后端返回状态码是Token已过期的状态码
if (isTokenExpired(Number(res.code))) {
// 刷新token
if(!isRefreshToken){
isRefreshToken=true
return store.dispatch('user/refreshToken').then(({ data }) => {
if (data.token) {
setToken(data.token, data.rtoken)
// 更新请求头
const params = response.config.params
if (params && params.token) params.token = data.token
refreshRequest.forEach(callback=>{
callback(data.token)
})
return service(response.config)
} else {
// 刷新失败需要重新登录
toLogin()
return Promise.reject()
}
}).catch(toLogin).finally(()=>{
isRefreshToken=false
})
}else{
// 缓存请求列表(利用Promise防止之前的请求返回错误的Token导致的错误信息)
return new Promise((resolve) => {
// 将resolve放进队列,等token刷新后直接执行
refreshRequest.push((token) => {
// 更新请求头
response.config.headers['Authorization'] = token
resolve(service(response.config));
});
});
}
}