问题原因:
vue项目使用axios 封装,当token过期或者失效后,弹窗提示用户登陆失效,重新登陆。在一些页面中初始化时调了多个API,会出现多次弹出重新登陆的弹框
解决方案:
1、使用axios中的CancelToken,在判断登陆失败时,取消后面的API请求。
2、跳转路由,取消上一个页面未请求成功的API。
实现方式:
1、reques.js关键代码
//请求拦截器
const http = axios.create()
http.interceptors.request.use((config) => {
config.cancelToken = new axios.CancelToken((cancel) => {
//使用vuex 定义pushCancel,请求进来存入
store.dispatch('pushCancel', {cancelToken:cancel})
});
}),
//响应拦截器
http.interceptors.response.use((response) => {
if (response.status === 200) {
let result = response.data
if(result.code !== 200 && result.code) {
const msg = result.msg;
//判断登陆状态, 取消后续请求
if (result.code === 401) {
store.dispatch('clearCancel');
Message({
message: '登录状态已过期,请重新登陆!',
type: 'error'
});
location.href = '/login';
return false
}
Message({
message: msg,
type: 'error'
});
} else {
return response.data
}
}else {
console.log(`Error Message:${response.status} ${response.statusText}`);
}
},error{
if (axios.isCancel(error)) {
// 使用isCancel 判断是否是主动取消请求
return new Promise(() => {});
}else {
let _errorMsg = error.response ? error.response.data.msg : error.message;
if (_errorMsg !== '' && _errorMsg !== null) {
Message({
message: _errorMsg,
type: 'error',
duration: 3 * 1000,
dangerouslyUseHTMLString: false
});
}
return Promise.reject(error);
}
});
2、使用vuex全局变量存取
const store = new Vuex.Store({
state: {
axiosCancelArr:[],
},
mutations: {
PUSH_CANCEL(state, cancel){
state.axiosCancelArr.push(cancel.cancelToken);
},
CLEAR_CANCEL(state){
state.axiosCancelArr.forEach(e=>{
e && e()
});
state.axiosCancelArr = []
}
},
actions:{
pushCancel({commit}, cancel){
commit('PUSH_CANCEL', cancel)
},
clearCancel({commit}){
commit('CLEAR_CANCEL');
}
}
})
export default store
3、使用路由拦截器,跳转路由调用clearCancel方法,清空存入的信息。终止未请求成功的请求
router.beforeEach((to, from, next) => {
store.dispatch('clearCancel');
next();
});
总结:
1、当页面初始化调用多个API时,使用axios响应拦截器判断状态码,如果登陆token失效,弹出请重新登陆的提示,取消后面的请求,跳转到登陆页面。
2、跳转路由时使用路由拦截器,清除vuex存入的全局变量,取消后面的API请求。