切換頁面時中斷
一、概述
在Vue單頁面開發過程中,遇到這樣的情況,當我切換頁面時,由於上一頁面請求執行時間長,切換到該頁面時,還未執行完,這時那個請求仍會繼續執行直到請求結束,此時將會影響頁面性能,並且可能對現在頁面的數據顯示造成一定影響
所以我們應該,切換頁面前中斷前面所有請求
二、解決方法
在main.js中,重新封裝axios請求,在router.beforeEach強制中斷請求
Vue.prototype.$http= axios;
//Vue函數添加一個原型屬性$axios 指向axios,這樣vue實例或組件中不用再去重復引用Axios 直接用this.$axios就能執行axios 方法
const CancelToken = axios.CancelToken;
Vue.$httpRequestList=[];
Vue.prototype.$ajax = (type, url, data) => {
return new Promise((resolve, reject) => { //封裝ajax
var aa = {
method: type,
url: url,
cancelToken: new CancelToken(c => { //強行中斷請求要用到的
Vue.$httpRequestList.push(c);
})
}
var json = (type == 'get') ? Object.assign(aa, { params: data }) : Object.assign(aa, { data: data });
var ajax = Vue.prototype.$http(json).then(res => {
resolve(res);
}).catch(error => { //中斷請求和請求出錯的處理
if (error.message == "interrupt") {
console.log('已中斷請求');
return;
} else {
reject(error);
}
})
return ajax;
})
};
router.beforeEach((to, from, next) => { //路由切換檢測是否強行中斷,
if(Vue.$httpRequestList.length>0){ //強行中斷時才向下執行
Vue.$httpRequestList.forEach(item=>{
item('interrupt');//給個標志,中斷請求
})
}
next();
});
使用請求
this.$axios('get',url,param).then(res=>{
}).catch(err=>{
});
三、分析解讀
axios中文官網(http://www.axios-js.com/zh-cn/docs/)對cancel token 的說明
使用cancel token取消請求
方法一、使用cancelToken.sourse工廠方法創建cancel token
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 處理錯誤
}
});
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
// 取消請求(message 參數是可選的)
source.cancel('Operation canceled by the user.');
方法二、通過傳遞一個 executor 函數到 CancelToken
的構造函數來創建 cancel token:
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函數接收一個 cancel 函數作為參數
cancel = c;
})
});
// cancel the request
cancel();
重復請求時中斷
instance.interceptors.request.use(config => {
config.cancelToken = new CancelToken(c => {
if(hasKey(this.queue,url)) {
c(url);
}else{
this.queue[url] = true;
};
})
return config
}, error => {
//return Promise.reject(error)
})