Open libin1991 opened 6 years ago
之前分析了两篇文章
这篇文章,来分析下取消请求是怎么实现的,先从一个简单的取消请求的例子开始:
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文件中。
axios/lib/axios.js
axios.CancelToken = require('./cancel/CancelToken');
不费吹灰之力,就找到了CancelToken,在例子中我们调用了source方法,那么就去axios/lib/cancel/CancelToken.js文件中看看这个source方法到底是干什么的?
axios/lib/cancel/CancelToken.js
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函数。
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就是用来触发取消请求的函数。
现在再回头来看,上面的cancel函数,cancel执行,给token加了一个reason属性,那么看下这个reason属性是什么吧,看下这个Cancel构造函数,在axios/lib/cancel/Cancel.js文件中
axios/lib/cancel/Cancel.js
function Cancel(message){ this.message = message }
Cancel特别简单就是给实例化对象添加一个message属性,所以现在token.reason是一个具有message属性的对象了。
继续回到cancel函数中,resolvePromise函数执行了,那么token.promise对象,这个原本未变成,成功状态的promise,变成了成功状态了,并且将token.reason对象传递过去了。
简单总结一下,执行取消函数,就是让token的promise的状态变成了成功;
好了,突然发现分析中断了,变成成功状态又怎样了,怎么取消的呢?虽然现在的同步代码都执行完了,但是请求还没发送出去呢,我们还要去看发送请求的函数,发送请求的过程已经在之前的文章中分析过了,传送门,戳这里。
在分析发送请求之前,再看下最开始的例子,和最普通的发送一个get请求还是有一点区别的,配置对象中多了,一个cancelToken的属性,值是token,到底起了什么作用呢,去axios/lib/adapters/xhr.js中一探究竟(这里只截取其中关于cancelToken的部分)。
axios/lib/adapters/xhr.js
// 在发送请求之前,验证了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的状态是否已经变了,如果变了,就取消请求,就是这样一个简单的思想来进行取消请求的。
之前分析了两篇文章
这篇文章,来分析下取消请求是怎么实现的,先从一个简单的取消请求的例子开始:
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
文件中。axios.CancelToken = require('./cancel/CancelToken');
不费吹灰之力,就找到了CancelToken,在例子中我们调用了source方法,那么就去
axios/lib/cancel/CancelToken.js
文件中看看这个source方法到底是干什么的?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函数。
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就是用来触发取消请求的函数。
现在再回头来看,上面的cancel函数,cancel执行,给token加了一个reason属性,那么看下这个reason属性是什么吧,看下这个Cancel构造函数,在
axios/lib/cancel/Cancel.js
文件中function Cancel(message){ this.message = message }
Cancel特别简单就是给实例化对象添加一个message属性,所以现在token.reason是一个具有message属性的对象了。
继续回到cancel函数中,resolvePromise函数执行了,那么token.promise对象,这个原本未变成,成功状态的promise,变成了成功状态了,并且将token.reason对象传递过去了。
简单总结一下,执行取消函数,就是让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的状态是否已经变了,如果变了,就取消请求,就是这样一个简单的思想来进行取消请求的。