Axios 请求二次重发
定义相关变量与函数
定义 Axios 的 baseUrl
const BASE_URL = process.env.VUE_APP_BASEURL
定义 Token
的刷新状态
let isRefreshing = false
定义 Token
失效后,发送的请求的容器 – 缓存接口
let subscribers = []
定义函数, 刷新 Token
后, 将缓存的接口重新请求一次,请求发送以后,清空容器
function onAccessTokenFetched(newToken) {
subscribers.forEach(callback => {
callback(newToken)
})
// 清空缓存接口
subscribers = []
}
定义函数,添加请求失败的接口到容器中
function addSubscriber(callback) {
subscribers.push(callback)
}
Axios 拦截器配置
import { getUserToken } from 'your/api/path'
axios.interceptors.response.use(
response => {
console.log('response :>> ', response)
// {
// config: {
// headers: {
// Authorization: ''
// }
// method: '',
// url: ''
// },
// data: {},
// status: 200,
// statusText: 'OK'
// }
if (response.status === 200) {
if (response.data.code === 0) {
return response.data.data
}
return Promise.reject(new Error(response.data.msg))
} else if (response.status === 401) {
/**
* 将未授权接口缓存起来。retryOriginalRequest 这个 Promise 函数很关键,它一直处于等待状态。
* 只有当 token 刷新成功后,onAccessTokenFetched 这个函数执行了回调函数,返回了 resolve 状态
*/
const retryOriginalRequest = new Promise(resolve => {
addSubscriber(newToken => {
resolve(
axios.request({
...response.config,
headers: {
...response.config.headers,
Authorization: newToken,
},
})
)
})
})
// 无感刷新Token
if (!isRefreshing) {
isRefreshing = true
getUserToken({
grant_type: 'refresh_token',
refresh_token: localStorage.getItem('SYS_REFRESH_TOKEN'),
scope: 'server',
})
.then(refreshRes => {
const newToken = `${refreshRes['token_type']} ${refreshRes['access_token']}`
const newRefreshToken = refreshRes['refresh_token']
localStorage.setItem('SYS_TOKEN', newToken)
localStorage.setItem('SYS_REFRESH_TOKEN', newRefreshToken)
// 当刷新成功后, 重新发送缓存请求
onAccessTokenFetched(newToken)
})
.catch(() => {
// 刷新token报错的话, 就需要跳转到登录页面
localStorage.setItem('SYS_TOKEN', '')
localStorage.setItem('SYS_REFRESH_TOKEN', '')
window.location.href = '/login'
})
.finally(() => {
isRefreshing = false
})
}
return retryOriginalRequest
} else {
return Promise.reject(new Error(response.statusText))
}
},
error => {
return Promise.reject(new Error(error))
}
)