在開發vue項目中,請求是不可缺少的,在發送請求時常常需要統一處理一些請求頭參數等設置與響應事件,這時利用請求攔截器再好不過。
這里以axios請求為例
實現了設置統一請求頭添加token, 其中token在登錄時被存入了localStorage中。
同時攔截器利用new cancelToken與定義的cancelPending方法實現了可以取消正在pending狀態的請求,什么情況會需要取消請求呢?
如下兩種情況:
1.?有一個局部分頁時,用戶快速點擊第2頁,然后繼續點擊第3頁,如果網絡不太穩定時,第2頁的請求正在發送中,還未響應,但第3頁的請求先響應了,過了一會第2?頁請求才響應,這時用戶處于第3頁,但看到的數據確是第2頁的,當然有人會說可以在發送請求過程中禁用掉分頁按鈕點擊,但我感覺體驗不太好,為何禁用呢,直接點擊第3頁時中斷掉之前相同的請求即可。
2.?切換路由時,上一路由頁面中仍有未響應的請求時切換了路由,應該把正在pending的所有請求中斷取消掉。
?
下面是完整實現axios請求攔截器與取消pending請求功能的代碼
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: {}}; // 返回接口返回的錯誤信息(這里返回空對象是為了避免控制臺報錯)
});