axios源码阅读笔记
在没有阅读axios源码之前我对它的理解一直是一个基于promise封装的ajax请求工具。当我通读了一遍axios源码之后,带给我很多认知上的变化,发现这个库有很多设计思想在里面。让我们带着下面这些疑问来看一下源码中是如何做的。
md
1、axios为什么可以做为方法直接调用,又可以做为对象使用? 如axios(config).then() 和 axios.create(config)
2、axios既可以在浏览器中使用又可以在服务端使用?
3、axios中的拦截器(请求和响应)是如何工作的?
4、axios中使用了哪些设计理念?
调试源码准备工作
当我们在阅读源码时一般需要边执行边看代码,这样可以快速理解代码的运行过程。因此我们需要在开发工具中配置调试工具。
第一步下载源码
bash
git clone https://github.com/axios/axios.git
第二步看文件的目录
找到README.md 和 CONTRIBUTING.md这两个文件,一般这上面会有说使用方法和开发指南。我们可以很容易看到下面的代码。
bash
- `npm run test` run the jasmine and mocha tests
- `npm run build` run rollup and bundle the source
- `npm run version` prepare the code for release
```bash
> npm run examples
# Open 127.0.0.1:3000
```
Running sandbox in browser
```bash
> npm start
# Open 127.0.0.1:3000
```
我们下载依赖包,然后构建项目,最后使用启动命令可以在本地跑起来一个服务,默认配置的服务端口是3000。具体的package.json文件中有命令运行配置,想更详细的了解的看一下相关命令。
基于这个服务我们可以在浏览器打开,借助chorme进行调试相关的代码了。但这种方式调试不是最直接的源码,还是不太直观。
第三步在vscode中添加相应调试方法
下面我们在vscode中添加相应的调试方法。


🔗url
要改成你启动服务的端口号,webRoot
是用来解析 sourcemap
启动npm run start 本地启动一个服务端口,然后点击调试运行工具(三角形),这样就会打开一个chrome(这里我配置的是chrome,也可以改成其他的浏览器)浏览器就可以调试了。

axios源码解析
先来看一下axios目录的结构

axios的初始化过程
我们在入口文件处 axios = createInstance(defaults) 加上断点,可以了解整个axios的初始化过程。

初始化流程核心如上图,从这段源码就可以明白为什么axios即可以做方法也可以作为对象使用了,返回的axios是一个wrap函数,在wrap函数上我们挂在了很多Axios原型方法、create方法以及属性,源码中还在axios中挂载了其他的配置,详细可以看源码。
下面断点调试看一下流程



这里可以看到extend方法就是将传入的Axios.prototype中的方法通过bind重新指定指向绑定到axios实例上。
将所有的配置挂载到axios,并暴露出来。
axios在浏览器中调用流程
这里使用项目中提供的demo进行测试。

上面我们可以看到使用拦截器,会将我们提供的成功和失败回调放入到handlers中。后面在实际请求的时候回用到。进入到axios请求中,可以看到再次进入到bind方法了。

我们再次进入方法内部会看到调用request方法
这里插入一个说明,我们使用的post、get等方法也是在这个核心类中定义的,本质都是调用request方法。

这里进行了默认配置和我们传入的配置进行了合并操场

接下来处理了前面我们设置的拦截器相关的回调方法。请求拦截器将回调方法向队头插入,响应拦截器将回调方法向队尾插入


不是异步的请求头拦截器就在这里被调用执行,可以看到promise.then()中每次取出两个方法刚好对应前面设置的成功回调和失败回调。
再来看下面这段代码,可以看到取消请求配置,请求参数处理。我们停留的位置看到适配器了,这里的处理就是我们为什么可以在浏览器、node端都可以使用的原因,adapter配置了【'xhr','fetch','http'】,可以根据我们不同的环境调用不同的请求封装。

默认是用ajax的方式进行请求的,我们进入方法内容看一下具体实现。


成功之后回再次回到这里,执行响应拦截器相关回调方法。

到这里差不多就处理完了请求到响应相关的流程了。
总结
axios在架构设计上拆分了不同的功能模块,通过不同的属性、方法来乔接不同的功能。在源码中我们看到了不少的设计在里面,如取消请求中使用了发布订阅的模式、兼容不同平台使用适配器的模式、创建实例使用工厂模式、以及函数式编程的方式,参数的归一化处理等。这次的源码阅读还是很有收获,下一步计划看一下lodash源码。