以前分析了两篇文章javascript
这篇文章,来分析下取消请求是怎么实现的,先从一个简单的取消请求的例子开始:java
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/get?name=xmz', {
cancelToken : source.token
}).then((response)=>{
console.log('response', response)
}).catch((error)=>{
if(axios.isCancel(error)){
console.log('取消请求传递的消息', error.message)
}else{
console.log('error', error)
}
})
// 取消请求
source.cancel('取消请求传递这条消息');
复制代码
这就是一个简单的取消请求的例子,那么就从最开始的axios.CancelToken来看,先去axios/lib/axios.js
文件中。ios
axios.CancelToken = require('./cancel/CancelToken');
复制代码
不费吹灰之力,就找到了CancelToken,在例子中咱们调用了source方法,那么就去axios/lib/cancel/CancelToken.js
文件中看看这个source方法究竟是干什么的?axios
CancelToken.source = function(){
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c
})
return {
token : token,
cancel : cancel
}
}
复制代码
source方法很简单,就是返回一个具备token和cancel属性的对象,可是token和cancel都是经过CancelToken这个构造函数来的,那么还在这个文件中向上看,找到CancelToken函数。promise
function CancelToken (executor){
// ...
// 判断executor是一个函数,否则就报错
var resolvePromise;
this.promise = new Promise(function(resolve){
resolvePromise = resolve;
})
var token = this;
// 以上token如今有一个promise属性,是一个未成功的promise对象;
executor(function cancel(message){
if(token.reason){
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
})
// 这个cancel函数就是 上面函数中的cancel,也就是source.cancel;
}
复制代码
如今知道了source.cancel是一个函数,souce.token是一个实例化对象,暂时就知道这些,继续看文章最开始的例子,接下来是去发送请求了,最下面还有一行代码是执行souce.cancel();函数
souce.cancel就是用来触发取消请求的函数。post
如今再回头来看,上面的cancel函数,cancel执行,给token加了一个reason属性,那么看下这个reason属性是什么吧,看下这个Cancel构造函数,在axios/lib/cancel/Cancel.js
文件中ui
function Cancel(message){
this.message = message
}
复制代码
Cancel特别简单就是给实例化对象添加一个message属性,因此如今token.reason是一个具备message属性的对象了。this
继续回到cancel函数中,resolvePromise函数执行了,那么token.promise对象,这个本来未变成,成功状态的promise,变成了成功状态了,而且将token.reason对象传递过去了。spa
简单总结一下,执行取消函数,就是让token的promise的状态变成了成功;
好了,忽然发现分析中断了,变成成功状态又怎样了,怎么取消的呢?虽然如今的同步代码都执行完了,可是请求还没发送出去呢,咱们还要去看发送请求的函数,发送请求的过程已经在以前的文章中分析过了,传送门,戳这里。
在分析发送请求以前,再看下最开始的例子,和最普通的发送一个get请求仍是有一点区别的,配置对象中多了,一个cancelToken的属性,值是token,到底起了什么做用呢,去axios/lib/adapters/xhr.js
中一探究竟(这里只截取其中关于cancelToken的部分)。
// 在发送请求以前,验证了cancelToken,看来此处就是用来取消请求的;
if(config.cancelToken){
// 具体是如何取消的,是在这个判断内定义的;
config.cancelToken.promise.then(function(cancel){
request.abort();
reject(cancel);
request = null;
})
}
// 发送请求
request.send(requestData);
复制代码
仔细看这只是一个promise的then函数,只有在promise的状态变成成功后才会执行,而刚才咱们分析了,cancel就是让这个promise的状态变成成功,因此若是执行了,取消请求的函数,这个then就会执行,取消发送请求,而且把发送请求的promise变成reject,被axiox.get().catch()捕获;
流程已经清楚了,最后再总结一下:
执行cancel是让token的promise变成成功,在真正发送请求以前,验证token.promise的状态是否已经变了,若是变了,就取消请求,就是这样一个简单的思想来进行取消请求的。