axios源码分析——拦截器

4,251 阅读3分钟

上一篇中分析了axios发送一个简单的get请求的完整的流程,传送门,戳这里

这一篇讲主要来分析下axios是如何实现拦截器的,这里只分析请求拦截器。

axios.interceptors.request.use(function(config){
    // ...
    return config;
}, function(err){
    // ...
    return Promise.reject(err)
})

上面的代码就是定义一个请求的拦截器,需要注意的是拦截器是要在发送请求之前定义的!

axios是一个函数我们都知道了,interceptors属性是什么时候定义上的呢?上一篇分析了axios上好多属性都是从context和instance上继承来的,所以还是按照整个思路分析,来看axios/lib/core/Axios.js文件。

function Axios(){
    this.interceptors = {
        request = new InterceptorManager()
    }
}

context是Axios的实例化对象,有interceptors对象,所以axios继承来,也是可以访问的到的,清楚这一点就顺势去axios/lib/core/InterceptorManager.js文件中看InterceptorManager这个构造函数吧!

function InterceptorManager(){
    this.handlers = [];
}
InterceptorManager.prototype.use = function use(fulfilled, rejected){
    this.handlers.push({
        fulfilled : fulfilled,
        rejected : rejected
    });
    return this.handler.length - 1;
}

从上面可以看到,use是定义在构造函数的原型上的,所以它的实例化对象是可以访问的,所以到现在,axios.interceptors.request.use()我们已经解释清楚了,就是上面的函数,进入函数看下到底做了什么,我们定义的完成和失败的两个回调函数被push到一个handlers数组中去了,那么这个handlers数组到底有什么意义呢?

目前来说好像分析被中断了,不知道该如和进行下去,但是上一节我们在分析Axios.prototype.request方法的时候省略过一些关于拦截器的东西,去看看axios/lib/core/Axios.js

Axios.prototype.request = function(config){
    // ... 
    // 对config进行处理的代码还是省略掉
    var chain = [dispatchRequest, undefind];
    var promise = Promise.resolve(config);
    this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor){
        // 这是上一节分析省略掉的一个函数   
        // 关于这个forEach函数就是去遍历 刚才不知道是什么用的handlers数组;
        chain.unshift(interceptor.fulfilled, interceptor.rejected);
        // 就是把我们定义的拦截器的回调函数加入到chain的首部
    })
    // 关于response的也省略掉
    // 假设我们只定义了一组拦截器回调函数,那么现在chain应该是这样的
    // chain = [fulfilled, rejected, dispatchRequest, undefined];
    while(chain.length){
        promise = promise.then(chain.shift(), chain.shift())
    }
    // 经过循环这个promise就成了
    /**
     * promise = promise.resolve(conifg)
     *      .then(interceptor.fulfilled, interceptor.rejected)
     *      .then(dispatchRequest, undefined)
     */
    return promise
}

结合上一篇我们知道这个函数返回的promise是我们发送请求之后的promise,但是在发送请求之前先执行了fufilled(config)和rejected(err)组成的promise,这个promise执行并且resolve后才会去执行dispatchRequest(config);如果返回了reject那么请求promise将终止,会被axios.get().catch()捕获,所以这就是所谓的拦截。

对响应拦截器的处理也同样是这个道理,只是将interceptor.fulfilled和interceptor.rejected回调放在了chain数组的后面,再此就不做分析啦!

总结一下,这个其实流程挺简单的,就是把拦截器的回调,放到发送请求的promise之前,先执行。

关于取消请求的分析,传送门,戳这里