Vue踩坑日记之cancelToken
2018-07-05 本文已影响47人
alex夏夜
在真实项目中,当路由已经跳转,而上一页的请求还在pending状态,如果数据量小还好,数据量大时,跳到新页面,旧的请求依旧没有停止,这将会十分损耗性能,这时我们应该先取消掉之前还没有获得相应的请求,再跳转页面。这里axios给我们提供了一个方法:
cancelToken
让我们来看看cancelToken的使用方法:
官网方法一:
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');
如果我要跳转页面的话,我调用source.cance()方法就可以干掉之前这个没有请求完的请求了。
但是这个方法有个弊端,就是比较麻烦,每次都要手动去调用source.cance()方法。怎么做到全局统一管理呢?
官网给了以下方法:
还可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token:
var CancelToken = axios.CancelToken;
var cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
})
});
// 取消请求
cancel();
根据这个方法:我们一步一步来实现它:
在main.js里写一个全局httpRequestList的空数组,用来装我们的cancel函数:
// main.js
Vue.$httpRequestList = []
再在我们封装好的post,get请求里面,将每一个请求里面都做一个将cancel函数推入的httpRequestList数组的动作:
POST (url, data, errMsg) {
const CancelToken = axios.CancelToken
return axios.post(url, data, {
timeout: 30000,
cancelToken: new CancelToken(function executor (c) {
Vue.$httpRequestList.push(c)
})
}).then(checkStatus).then(res => checkCode(res, errMsg))
},
GET (url, params, errMsg) {
const CancelToken = axios.CancelToken
return axios.get(url, {
params: {
_t: +(new Date()),
...params
},
timeout: 30000,
cancelToken: new CancelToken(function executor (c) {
Vue.$httpRequestList.push(c)
})
}).then(checkStatus).then(res => checkCode(res, errMsg))
}
这样我们的每一个请求里面,都包含了一个cancelToken对象。
在这之后我们要写一个执行cancel方法的 方法:
import Vue from 'vue'
export const clearHttpRequestingList = () => {
if (Vue.$httpRequestList.length > 0) {
Vue.$httpRequestList.forEach((item) => {
item()
})
Vue.$httpRequestList = []
}
}
item就是之前每一个请求装进httpRequestList数组的cancel方法,item()执行后,如果该请求是pending状态,那么可以直接取消掉。执行完后记得清空httpRequestList数组。
最后我们回到main.js
在每次跳转之前执行clearHttpRequestingList()函数。
router.beforeEach((to, from, next) => {
clearHttpRequestingList()
..........这下面是你的路由验证代码..........
})
这样就实现了每次路由跳转之前,就清空之前出于pending状态的请求,优化了性能。
如下图所示: