axios源码浅析

97 阅读25分钟

1.区别一般http请求与ajax请求

  1. ajax 请求是一种特别的 http 请求
  2. 对服务器端来说, 没有任何区别, 区别在浏览器端
  3. 浏览器端发请求: 只有 XHR 或 fetch 发出的才是 ajax 请求, 其它所有的都是
    非 ajax 请求
  4. 浏览器端接收到响应
    (1) 一般请求: 浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/
    跳转页面
    (2) ajax 请求: 浏览器不会对界面进行任何更新操作, 只是调用监视的回调
    函数并传入响应相关数据

2.axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

中文文档:www.axios-js.com/zh-cn/docs/

3.源码分析

3.1 源码目录结构

├── /dist/                                      # 项目输出目录

├── /lib/                                        # 项目源码目录

    │ ├── /adapters/                          # 定义请求的适配器 xhr、 http

        │ │ ├── http.js                             # 实现 http 适配器(包装 http 包)

    │ │ └── xhr.js                               # 实现 xhr 适配器(包装 xhr 对象)

    │ ├── /cancel/                              # 定义取消功能

    │ ├── /core/                               # 一些核心功能

        │ │ ├── Axios.js                           # axios 的核心主类

        │ │ ├── dispatchRequest.js       # 用来调用 http 请求适配器方法发送请求的函数

        │ │ ├── InterceptorManager.js   # 拦截器的管理器

    │ │ └── settle.js                          # 根据 http 响应状态, 改变 Promise 的状态

    │ ├── /helpers/                           # 一些辅助方法

    │ ├── axios.js                             # 对外暴露接口

    │ ├── defaults.js                         # axios 的默认配置

│ └── utils.js                          # 公用工具

├── package.json                     # 项目信息

├── index.d.ts                            # 配置 TypeScript 的声明文件

└── index.js                                # 入口文件

入口文件直接引用lib/axios.js

3.2 源码浅析

3.2.1axios请求

在axios.js中

可以看出

  • axios 是 Axios.prototype.request 函数 bind()返回的函数
  • 同时 axios 作为对象有 Axios 原型对象上的所有方法, 有 Axios 对象上所有属性
  • 换句话讲, 从语法上来说: axios 不是 Axios 的实例 ,从功能上来说: axios 是 Axios 的实例
  • 这样axios就对应了文档中既可以通过向 axios 传递相关配置来创建请求,也可以通过别名进行便捷请求

3.2.1.1 创建实例

文档中创建实例:

根据指定配置创建一个新的 axios, 也就就每个新 axios 都有自己的配置

基本用法:

(1) 需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一
样, 如何处理
(2) 解决: 创建 2 个新 axios, 每个都有自己特有的配置, 分别应用到不同要
求的接口请求中

源码:

和创建axios使用相同的函数。因此相同点

(1) 都是一个能发任意请求的函数: request(config)
(2) 都有发特定请求的各种方法: get()/post()/put()/delete()
(3) 都有默认配置和拦截器的属性: defaults/interceptors

又因为传入的配置可能不同,同时create函数之下的函数在返回的axios并不存在,不同点

(1) 默认匹配的值很可能不一样
(2) instance 没有 axios 后面添加的一些方法: create()/CancelToken()/all()

3.2.2 Axios.prototype.request()

上一节可知,axios函数执行的是Axios.prototype.request()函数。

在lib/core/Axios.js中我们可以看到Axios.prototype.request()函数

源码:

request(config)函数执行流程: 

将请求拦截器 / dispatchRequest() / 响应拦截器 通过 promise 链串连起来,返回 promise 。

通过操作数组chain,配合promise链式执行数组中的函数。

首先将请求拦截器unshift到数组,再将响应拦截器push到数组,这样就决定了当有多个拦截器时的执行顺序。

如图,多个拦截器的执行顺序。

**3.2.3 dispatchRequest(config)函数 **

dispatchRequest(config)函数执行流程:

转换请求数据 ===> 调用 xhrAdapter()发请求 ===> 请求返回后转换响应数据,返回 promise  。

数据转换:

源码:

默认配置(defaults.js)

请求数据转换:

响应数据转换: