axios拦截器执行顺序的源码解释

本文深入剖析了Axios库的请求流程,详细解读了请求和响应拦截器的执行顺序及其实现原理,揭示了Promise链如何串联整个请求过程。

axios拦截器执行顺序的源码解释

我们先来看一段代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js"></script>
    <script>
        //添加请求拦截器(回调函数)
        axios.interceptors.request.use(
            config => {
                console.log('request interceptor1 onResolved()')
                return config
            },
            error => {
                console.log('request interceptor1 onRejected()')
                return Promise.reject(error)
            }
        )
        axios.interceptors.request.use(
            config => {
                console.log('request interceptor2 onResolved()')
                return config
            },
            error => {
                console.log('request interceptor2 onRejected()')
                return Promise.reject(error)
            }
        )
        //添加响应拦截器
        axios.interceptors.response.use(
            response => {
                console.log('response interceptor1 onResolved()')
                return response
            },
            error => {
                console.log('response interceptor1 onRejected()')
                return Promise.reject(error)
            }
        )
        axios.interceptors.response.use(
            response => {
                console.log('response interceptor2 onResolved()')
                return response
            },
            error => {
                console.log('response interceptor2 onRejected()')
                return Promise.reject(error)
            }
        )

        axios.get('http://localhost:3000/posts')
            .then(response => {
                console.log('data', response.data);

            })
            .catch(error => {
                console.log('error', error.message)
            })
    </script>
</body>

</html>

通过运行这段程序,我们可以在控制台看到分别打印的是:

request interceptor2 onResolved()
request interceptor1 onResolved()
response interceptor1 onResolved()
response interceptor2 onResolved()
data

那么为什么会出现这样的结果吗?通过查看axios的源码,我知道了答案,下面分享给大家
我摘取源码中关于这个的部分进行解释:

Axios.prototype.request = function request(config) {
  /*eslint no-param-reassign:0*/
  // Allow for axios('example/url'[, config]) a la fetch API
  if (typeof config === 'string') {
    config = arguments[1] || {};
    config.url = arguments[0];
  } else {
    config = config || {};
  }

  // 合并配置
  config = mergeConfig(this.defaults, config);
  // 添加method配置, 默认为get
  config.method = config.method ? config.method.toLowerCase() : 'get';

  /*
  创建用于保存请求/响应拦截函数的数组
  数组的中间放发送请求的函数
  数组的左边放请求拦截器函数(成功/失败)
  数组的右边放响应拦截器函数
  */
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  // 后添加的请求拦截器保存在数组的前面
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });
  // 后添加的响应拦截器保存在数组的后面
  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });
  

  // 通过promise的then()串连起所有的请求拦截器/请求方法/响应拦截器
  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

  // 返回用来指定我们的onResolved和onRejected的promise
  return promise;
};

这个request方法就是axios发送请求的核心方法,在源码中将发送请求分为了几个部分(请求拦截器,发送请求,响应拦截器,响应回调),通过Promise的链式调用将这些部分有机地结合了起来,这样就构成了发送请求拿到数据处理的全部过程。
下面我们一一分析:

  1. 代码开始构建了一个config配置对象,用于第一次执行Promise返回一个成功的promise
  2. 最核心的数组chain,这个数据中保存了请求拦截器函数,响应拦截器函数和默认就有的发送请求的函数,第一步返回的成功的promise对象,将遍历这个数组逐一执行里面的函数,并返回新的Promise对象
  3. 往数组中添加请求拦截器函数,依照axios请求的执行顺序,请求拦截器应该在发送请求之前执行,故应该添加在发送请求函数的前面,所以使用的是数组的unshift方法,这个方法意思是头部添加,即后面添加的元素总是在头部
  4. 往数组中添加请求拦截器函数,依照axios请求的执行顺序,响应拦截器应该在发送请求之后执行,故应该添加在发送请求函数的后面,所以使用的是数组的push方法,这个方法意思是尾部添加,即后面添加的元素总是在尾部
  5. promise遍历执行,使用的while循序,使用数组的shift方法每次从中取出两个函数执行(成功回调,失败回调)
  6. 返回Promise对象,用于执行我们指定的响应数据的回调

相信我说到这里,大家就已经懂了,不要需要伙伴们对Promise有一定的理解,不懂的小伙伴可以先看看Promise是什么

下面,我把图给大家看一看:
在这里插入图片描述
其中,还有一些细枝末节的地方我没讲,因为我也不懂,我只知道它大概是这么个执行流程,我能理解的都讲了,望大家采纳!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值