在開發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: {}}; // 返回接口返回的錯誤信息(這裏返回空對象是爲了不控制檯報錯) });