根据文档做出一个全局统一处理的请求取消 https://www.runoob.com/vue2/vuejs-ajax-axios.html,这里第二种方法,直接获取cancel方法,然后直接执行cancel方法
1.main.js
Vue.prototype.Cancel = [];
在vue原型上声明一个全局变量 cancel用来保存在请求时的cancel方法
2.统一请求拦截封装 http.js
let http = axios.create({
timeout: 15000,
headers: {
'Content-Type' : 'application/json;charset=UTF-8'
},
});
let _this = Vue.prototype;
// 请求拦截
http.interceptors.request.use(config => {
// console.log("请求信息:")
// console.log(JSON.stringify(config))
config.cancelToken = new axios.CancelToken(function (cancel) {
_this.Cancel.push(cancel);
});
请求拦截里获取请求时的cancel,添加到Cancel数组中
3.router.js
Vue.prototype.Cancel && Vue.prototype.Cancel.forEach(cancel => {
console.log(cancel)
cancel();// 执行cancel方法关闭请求
});
Vue.prototype.Cancel = [];
当路由变化时 遍历Cancel数组,执行cancel方法,然后清空数组
4.http.js响应拦截
return Promise.resolve(response)
}, error => {
// console.log("错误信息:")
// console.log(JSON.stringify(error))
if (axios.isCancel(error)) { // 如果是取消请求抛出的错误,终止Promise调用
_this.$closeLoad();
return new Promise(() => {});
}
在响应拦截中的错误里对取消请求抛出的错误终止promise调用链
5.axios的取消请求源码
'use strict';
var Cancel = require('./Cancel');
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
executor(function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
});
}
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
if (this.reason) {
throw this.reason;
}
};
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
module.exports = CancelToken;
分析:
1.CancelToken这个类初始化的时候需要传递一个executor参数,而且executor必须是一个function,在这个类的内部还创建了一个promise,并且分离了reslove,把控制权又交给了executor的执行体上
2.source这个方法中定义了一个变量cancel,并且在这个方法内new了一个CancelToken,传入一个参数c,然后将c赋值给了cancel,同样的是把executor方法的变量c的控制权给了cancel,而c又是在初始化CancelToken时传入的executor方法,既是上面代码中的
function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
}
也就是把上面这个方法赋值给了source方法中cancel属性,通过cancel可以控制CancleToken的promise对象,source方法中token属性是一个CancelToken实例,同样可以访问到CancelToken的promise对象
所以CancelToken目的是为了能够分离promise和resolve方法,让用户可以自主调用resolve,一旦resolve后就会触发promise的then方法,下面是then方法里代码,当进入then后会立即调用abort()原生方法取消请求,同时调用reject让外层的promise的失败
if (config.cancelToken) {
// Handle cancellation
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}