Axios中的interceptor与cancel

1,241 阅读3分钟

Axios是基于promise的网络请求库,其在node中会使用http对象发起网络请求,在浏览器环境中会使用XHR对象发起网络请求。

本文要探究的是interceptor的执行顺序与cancel取消请求的原理。最后封装一个可以后一个请求可以打断前一个请求的方法。

interceptor的请求顺序

案例:

在使用use方法设置多个拦截器,其注册属性如下

request1 -> request2 -> response1-> response2

存入数组

拦截器在理论上可以有无数个,这是因为axios内部使用数组保存了每一个拦截器。其使用user方法将拦截器存入数组中,源码如下。

拦截器在使用的时候是 axios.interceptors.request.use/ axios.interceptors.response.use

request/response为InterceptorManager的实例,因此可以使用实例上的user方法。


可以看出use方法很简单,只是把fulfilled方法与rejected方法出入数组中



从数组中取出

可以看出内部使用了名为chain的数组,在发起网络请求前,取出interceptors对象中request和response实例中存储的fulfilled与rejected函数。

注意:请求拦截器使用的是unshift方法;响应拦截器使用的是push方法


链式调用及顺序

chain数组中使用了undefinded占位,这因为在后面promise的链式调用中是用了shift方法从数组中取值,如果不使用undefined占位,会导致错位产生。

其中dispatchRequest是发送网络请求的核心,其会调用adapter对象发送网络请求


adapter方法

由于adapter方法太长了,这里就截取了部分代码,其原理也很简单,就是返回一个promise实例。

下面是其中一个代码片段,这里判断了cancelToken



那么文章一开始的执行顺序就有了答案:

request2 -> request1 -> response1-> response2


cancel取消请求

上方的代码片段中有对cancelToken的判断

那么就开始分析代码片段

config.cancelToken.promise.then ...

这里的出处如下:

1. axios对象上添加cancelToken方法,


2. new 一个cancelToken

可以在拦截器中设置config的cancelToken属性,也可以直接创建axios实例的时候设置

这里是在拦截器中设置


3. 执行promise链

在链式调用的时候 dispatchRequest调用之前,会对根据config对网络请求进行一列的配置。

到了dispatchRquest的时候会调用封装好的adapter方法。

在adapter方法中,会有对cancelToken的处理。

首先看一下cancelToken方法的封装



可以看出这里给CancelToken的实例上有一个promise属性,其值为一个promise实例。在这里使用了resolvePromise变量引用了resolve函数,因此来在外部控制这个promise实例的状态。


在配置config.cancelToken的时候会newCancelToken函数,使得config.cancelToken的值为一个新的promise实例(非chain数组中的onfulfilled, onrejected函数)。

这个新的promise实例会影响chain数组产生的prmoise链的执行状态。


c => cancel = c 的理解

cancelToken内部有如下executor函数

executor(function cancel(message){

    // 略。。。

})

传入c => cancel =c 的函数为executor,那么这样就可以把内部的cancel函数“取出”到外部,然后由执。

cancel函数内部会使用resolvePromise来决议这个新prmoise的状态,如果一直不调用cancel不会影响后续的终止动作,如果调用了就会终止网络请求。

其流程如下:

axios封装网络请求的中断

用后面的网络请求终止前面的网络请求


最后

cancelToken函数设计很巧妙,了解了cancelToken的工作流程之后会对promise有更加深入的了解。