vue項目中 axios請求攔截器與取消pending請求功能

在開發vue項目中,請求是不可缺乏的,在發送請求時經常須要統一處理一些請求頭參數等設置與響應事件,這時利用請求攔截器再好不過。vue

這裏以axios請求爲例ios

實現了設置統一請求頭添加token, 其中token在登陸時被存入了localStorage中。axios

同時攔截器利用new cancelToken與定義的cancelPending方法實現了能夠取消正在pending狀態的請求,什麼狀況會須要取消請求呢?網絡

以下兩種狀況:ui

1. 有一個局部分頁時,用戶快速點擊第2頁,而後繼續點擊第3頁,若是網絡不太穩定時,第2頁的請求正在發送中,還未響應,但第3頁的請求先響應了,過了一會第2 頁請求才響應,這時用戶處於第3頁,但看到的數據確是第2頁的,固然有人會說能夠在發送請求過程當中禁用掉分頁按鈕點擊,但我感受體驗不太好,爲什麼禁用呢,直接點擊第3頁時中斷掉以前相同的請求便可。url

2. 切換路由時,上一路由頁面中仍有未響應的請求時切換了路由,應該把正在pending的全部請求中斷取消掉。spa

 

下面是完整實現axios請求攔截器與取消pending請求功能的代碼code

let pending = [];
let    cancelToken = axios.CancelToken;
let    cancelPending = (config) => {
pending.forEach((item, index) => {
if(!!config){
if(item.u == config.url){
item.f(); //取消請求
pending.splice(index, 1); //移除當前請求記錄
};
}else{
item.f(); //取消請求
pending.splice(index, 1); //移除當前請求記錄
}
});
};

//驗證登陸狀態
router.beforeEach((to, from, next) => {
//若是是須要驗證登陸狀態的頁面
if(to.matched.some(record => record.meta.requireAuth)){
let token = localStorage.getItem('token');
//若是已經登陸,則正常進入
if(!!token){
cancelPending();
next();
}else{
next({'name': 'login', 'query': {'redirect': to.fullPath}});
};
}else if(to.name == 'login'){ //若是是登陸頁,則驗證若是當前是登陸狀態自動跳轉至系統主頁,不然正常進入登陸頁
let token = localStorage.getItem('token');
//若是已經登陸,則重定向至系統首頁
if(!!token){
router.push({'name': 'SystemWelcome'});
}else{
next();
};
}else{ //其餘頁面正常進入
next();
};
});


//axios 請求攔截器
axios.interceptors.request.use(config => {
let token = localStorage.getItem('token');
if (!!token) { // 判斷是否存在token,若是存在的話,則每一個http header都加上token
config.headers.Authorization = `token ${token}`;
};
cancelPending(config);
config.cancelToken = new cancelToken((c) => {
pending.push({'u': config.url, 'f': c});
});
return config;
}, err => {
return Promise.reject(err);
});
//響應攔截器
axios.interceptors.response.use(response => {
cancelPending(response.config);
return response;
}, error => {
if (error.response) {
switch (error.response.status) {
case 401:
// 返回 401 清除token信息並跳轉到登陸頁面
localStorage.removeItem('token');
router.push({'name': 'login', 'query': {'redirect': router.currentRoute.fullPath}});
}
}
return {data: {}}; // 返回接口返回的錯誤信息(這裏返回空對象是爲了不控制檯報錯)
});
相關文章
相關標籤/搜索