Axios源码分析

Axios主要就是在package.json里面配置然后安装就能在node_modules里面找到源码。git地址:https://github.com/axios/axios

Axios 的主要特性包括:

基于 Promise
支持浏览器和 node.js
可添加拦截器和转换请求和响应数据
请求可以取消
自动转换 JSON 数据
客户端支持防范 XSRF
支持各主流浏览器及 IE8+

Axios的使用

1
2
3
4
5
6
7
axios.get('/get?name=xmz')
.then((response)=>{
console.log('response', response)
})
.catch((error)=>{
console.log('error', error)
})

当业务请求代码发起时,具体执行的是lib/core/Axios.js中的request方法。

├── /dist/                     # 项目输出目录
├── /lib/                      # 项目源码目录
│ ├── /cancel/                 # 定义取消功能
│ ├── /core/                   # 一些核心功能
│ │ ├── Axios.js               # axios的核心主类---------------------------这是其最核心部分
│ │ ├── dispatchRequest.js     # 用来调用http请求适配器方法发送请求         |
│ │ ├── InterceptorManager.js  # 拦截器构造函数                            |
│ │ └── settle.js              # 根据http响应状态,改变Promise的状态--------
│ ├── /helpers/                # 一些辅助方法
│ ├── /adapters/               # 定义请求的适配器 xhr、http----这个文件夹封装了ajax的请求
│ │ ├── http.js                # 实现http适配器
│ │ └── xhr.js                 # 实现xhr适配器
│ ├── axios.js                 # 对外暴露接口
│ ├── defaults.js              # 默认配置 
│ └── utils.js                 # 公用工具
├── package.json               # 项目信息
├── index.d.ts                 # 配置TypeScript的声明文件
└── index.js                   # 入口文件

工厂函数createInstance

在找到axios/lib/axios.js里面有这个对象,var axios = createInstance(defaults);创建axios这样一个实例函数

axios/lib/defaults.js是默认配置,默认导出一个对象

配置:

  • 全局配置:提供配置参考,实例化的时候可以使用。
  • 实例配置:一个应用可能需要实例化多个不同的对象(针对不同的接口)所以每个实例化对象都会有自己的配置,可以通过全局配置进行初始化,或合并一个新的配置项
  • 请求配置:请求的时候需要传入配置与实例配置进行合并。不要影响(赋值引用)

深度克隆-deepcopy函数,深度克隆对象

配置合并-configMerge函数,有的是覆盖,有的是合并

拦截器Interceptor

在 Axios 中,大概是这样添加拦截器:

1
2
3
4
5
6
7
8
9
10
11
12
// Add a request interceptor
axios.interceptors.request.use(function (config) {
return config;
}, function (error) {
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
return response;
}, function (error) {
return Promise.reject(error);
});

interceptors.request -> request -> interceptors.response -> response
而 Axios 内部,很巧妙地实现了上面所说的管道式流程,首先看 lib/core/Axios.js。interceptors.request可以注册函数,在发送请求之前执行,interceptors.response在发送请求并得到数据后执行,then之前执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var dispatchRequest = require('./dispatchRequest');
function Axios(instanceConfig) {
this.defaults = instanceConfig;
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
Axios.prototype.request = function request(config) {
// 省略部分代码...
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);
});
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
// 省略部分代码...

先看到 Axios 类的定义里面有 interceptors,并且带有 request 和 response 属性,而这 2 个属性都是指向 InterceptorManager 类的实例。这个等下再说,先看 request 方法里 interceptors 的实现。

我们留意 chain 这个变量,经过 2 次 forEach 操作后,最后的值会变成:(这个 forEach 方法在 InterceptorManager 中定义)

  • 单请求配置Options:axios.post(url,data,options)
  • 全局配置Defaults:this.$axios.defaults
  • config:请求拦截器中的参数
  • response.config:响应拦截器中的参数
  • Options:

    -  baseURL 基础URL路径
    -  params 查询字符串对象
    -  transformRequest 转换请求体数据
    -  transformResponse 转换响应体数据
    -  headers:头信息
    -  data:请求体数据
    -  timeout:请求超时。 
    

    InterceptorManager管理拦截器

use()方法接收到两个参数,一个是fulfilled,一个是rejected

适配器adapters

通过适配器,把不同的接口进行适配。在adapter的处理逻辑中,axios没有把http和xhr两个模块(一个用于Node.js发送请求,另一个则用于浏览器端发送请求)当成自身的模块直接在dispatchRequest中直接饮用,而是通过配置的方法在default.js文件中进行默认引入。这样既保证了两个模块间的低耦合性,同时又能够为今后用户需要自定义请求发送模块保留了余地。

文章目录
  1. 1. 工厂函数createInstance
  2. 2. 拦截器Interceptor
    1. 2.1. InterceptorManager管理拦截器
  3. 3. 适配器adapters
本站总访问量 本站访客数人次 ,