参考:https://juejin.im/post/6844903925078818829
我们的ajax请求有2种情况:
-
并行请求
getData1();
getData2();
getData3();
-
回调请求
getData1().then(res => {getData2()}).catch(() => { });
需求运行到任何一个请求以后token失效了,这个时候我们应该refresh token,refresh成功以后,继续请求之前没成功的接口,并继续往下执行代码。
所以前提就是我们一定不能让axios请求错误在一定不能在error出现。
为什么呢,比如第二种情况getData1() 请求码401了直接进error肯定就是继续往下走catch里,就不会继续运行到getData2();就不符合我们的预期了,所以为了避免这种情况,我建议所有关于401的情况都变成code为200,但是给个{status: ‘401’,messasge: ‘token失效’}的返回
我直接上解决办法了:
let isRefreshing = false;
let requests = [];
// respone拦截器
service.interceptors.response.use(
response => {
/**
* code为非20000是抛错 可结合自己业务进行修改
*/
const res = response.data
if (res.status === "401" && store.getters.tokenInfo['refresh_token']) {
let formData = new FormData();
formData.append('refresh_token', store.getters.tokenInfo['refresh_token']);
const config = response.config
if (!isRefreshing) {
isRefreshing = true;
store.dispatch('refresToken', formData).then(async(res) => {
if (res.status === 'success') {
await store.commit('SET_TOEKN_INFO', res.result);
config.headers['authorization'] = 'Bearer ' + res.result['access_token'];
config.baseURL = ''
// 已经刷新了token,将所有队列中的请求进行重试
requests.forEach(cb => cb('Bearer ' + res.result['access_token']));
requests = []
return service(config);
} else {
// 清空用户消息和token信息
store.commit('SET_USER', {});
store.commit('SET_TOEKN_INFO', {});
router.push({ path: '/login' })
}
}).catch(() => {
router.push({ path: '/login' });
}).finally(() => {
isRefreshing = false;
});
} else {
// 正在刷新token,将返回一个未执行resolve的promise
return new Promise((resolve) => {
// 将resolve放进队列,用一个函数形式来保存,等token刷新后直接执行
requests.push((token) => {
config.baseURL = ''
config.headers['authorization'] = token
resolve(service(config))
})
})
}
}
if (res.status !== 'success') {
Message({
message: res.message,
type: 'error',
duration: 5 * 1000
})
} else {
return response.data
}
},
error => {
// 当响应异常时做一些处理
return Promise.reject(error);
}
)