前言
axios库提供了取消请求的功能,虽然个人平时很少用到。
正文
下面是官网的两个例子:
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
});
cancel();
第一个例子中,在axios请求时传递cancelToken
参数,该参数为CancelToken
的实例,创建该时可获取到cancel
函数的引用。调用cancel
函数即可取消请求。
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 {
// handle error
}
});
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
第二个例子中,使用CancelToken.source()
返回一个source
对象,包含了token
和cancel
,将token
传递给请求参数,然后调用cancel
即可取消对应的请求。
下面是axios的大体目录:
先从第一个例子开始,找到挂在axios
下的CancelToken
文件。看一下new CancelToken
时做了什么:
创建了一个promise,保持为pending状态。然后将cancel传递出去,函数中调用了resolve。而生成的实例有两个属性:this.promise
和this.reason
(这个reason是调用cancel时才被赋值的,作为是否已经取消过的标志)。而这个实例就被传递到cancelToken
请求参数中了。
下面看看cancelToken
请求参数在发送请求时起到的作用。在lib/core/Axios.js
中可以看到request函数,调用的是dispatchRequest
发送请求。
随带一提,request中使用了promise的链式调用,chain数组中包含了请求拦截器、响应拦截器,而dispatchRequest
则是夹在两者的中间。这就是Axios拦截器的原理。
那么我们就进入dispatchRequest.js
中看一下它做了什么:
可以看出adapter
是一个promise
,这个adapter
默认是什么呢?在default.js
中可以看到,adapter在浏览器端是XHR,在Node使用的是http(所以axios是兼容服务端的)。
adapter顾名思义是适配器的意思,这里也是使用了适配器设计模式,允许开发者自己传入请求对象。而不是将请求固定死为xhr或者Node.js的http库。
那么我们这里看一下xhr.js
,在这个文件中我们终于要发送请求了:
前面一堆根据config对xhr进行配置不看,直接看到最后的cancelToken
,我们可以看到,如果传递了cancelToken
参数,则在cancelToken
的promise
状态变为resolved
时执行:request.abort();
中断请求。
那么promise什么时候resolved呢?由前面所述,resolve函数被暴露出来赋值给cancel引用。那么,当我们调用cancel时,promise状态变为resolved,请求被取消。就是这样。
再来看看第二个例子,第二个例子就是进行了一下封装。由第一个例子可知,我们使用时需要的就是cancelToken
和对应的cancel
方法。axios提供一个静态方法,将两个东西一并返回给我们:
这样子,我们就不用像第一个例子那样还要传递一个回调函数来拿cancel函数了。