1

一、什么是axios

Axios(Promise based HTTP client for the browser and node.js): 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

二、axios和ajax的区别

AJAX( Asynchronous Javascript And XML ): 异步js和xml,是一种异步请求的技术。

1、区别

Axios是AJAX技术的一种实现。axios是通过Promise实现对ajax技术的一种封装,就像jquery对ajax的封装一样,简单来说就是ajax技术实现了局部数据的刷新,axios实现了对ajax的封装,axios有的ajax都有,ajax有的axios不一定有,总结一句话就是axios是ajax,ajax不止axios

2、优缺点

ajax:

  1. 本身是针对MVC编程,不符合前端MVVM的浪潮
  2. 基于原生XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案,jquery整个项目太大,单纯使用ajax却要引入整个jquery非常不合理(采取个性化打包方案又不能享受cdn服务)
  3. ajax不支持浏览器的back按钮
  4. 安全问题ajax暴露了与服务器交互的细节
  5. 对搜索引擎的支持比较弱
  6. 破坏程序的异常机制
  7. 不容易调试

axios:

  1. 从node.js创建http请求
  2. 支持Promise API
  3. 客户端防止CSRF(网站恶意利用)
  4. 提供了一些并发请求的接口

三、axios API

  1. axios.get(url[, config]) 执行 GET 请求
  2. axios.post(url[, data[, config]]) 执行 POST 请求
  3. axios.request(config)
  4. axios.head(url[, config])
  5. axios.delete(url[, config])
  6. axios.put(url[, data[, config]])
  7. axios.patch(url[, data[, config]])
  8. axios.all(iterable)执行多个并发请
  9. axios.spread(callback)处理并发请求

四、使用与源码解析

1、安装axios

npm方式:

$ npm install axios

bower方式:

$ bower install axios

cdn方式:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

2、项目目录结构


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

3、请求流程

image.png

  1. 当执行axios(url)或者axios[method]对应的都是Axios中的request方法
  2. 拦截器interceptors收集订阅,顺序为,请求拦截器,dispatchRequest,响应拦截器
  3. 拦截器Promise.then(chain.shift())执行,首先执行请求拦截器,并改变原订阅数组
  4. 直至dispatchRequest触发config.adapter(客户端是XMLHttpRequest, 返回Promise)
  5. 后继续Promise.then(chain.shift()),执行响应拦截器,直至订阅数组长度为0

在过程4,dispatchRequest触发请求即XMLHttpRequest的执行过程是,open初始化,绑定所有方法,添加属性和配置后,send发起请求。

过程中执行绑定的方法,非预期时reject;只有当readyState为4时,才有可能resolve拿到我们期望的数据。

常见的使用Axios的方法总是配合着then + catch或async/await + catch使用。

4、项目文件分析


1、/lib/axios.js

随入口 index.js 进入/lib/axios.js,该文件主要创建Axios的实例和向外暴露接口

  1. 通过createInstance()方法创建实例

    • 实例instance指向了Axios原型的request方法,上下文指向context,因此可以直接以 instance(option) 方式调用
    • 把Axios.prototype上的方法扩展到instance对象上,指定上下文为context,这样执行Axios原型链上的方法时,this会指向context
    • 把context对象上的自身属性和方法扩展到instance上,这样,instance 就有了 defaults、interceptors 属性
  2. 向外暴露的接口

    • 在导出的默认的实例不满足要求时,使用create方法创建新的axios实例
    • 取消请求时抛出的Cancel对象、用于请求取消操作的对象CancelToken和标记是否取消请求的isCancel方法
    • 用于处理并发请求的all、spread方法

2、/lib/core/Axios.js

该文件是axios的核心主类,包含创建axios实例时用到的Axios类、dispatch请求、获取请求链接、针对请求时是否携带data分别为方法提供别名

  1. Axios类指定了创建实例的默认配置,并且为Axios类指定了拦截器:request请求拦截器和response响应拦截器,二者均为拦截管理器的实例。其中request请求拦截器的作用是在请求发送前进行一些操作,例如在每个请求体里加上token,设置请求头headers、应用的版本号等。response响应拦截器的作用是在接收到响应后根据响应的状态码进行一些操作,例如:由于当前的token过期,接口返回401未授权,那我们就要进行重新登录的操作。
  2. Axios.prototype.request方法是dispatch请求的过程

    • 根据用户提供的配置设置请求的url和方法,如果没有提供方法则设置方法为默认配置中的方法,否则方法设置为get
    • 将chain数组作为连接拦截器中间件,将拦截器添加到chain数组中,添加后的数组大致形式为:

      requestFulfilledFn, requestRejectedFn, ...,

      dispatchRequest, undefined,

      responseFulfilledFn, responseRejectedFn, ....,

      通过while循环中chain数组的shift操作执行请求拦截器,dispatchRequest 方法一定会等待所有的请求拦截器执行完后再开始执行,响应拦截器一定会等待 dispatchRequest 执行完后再开始执行。

    • 为支持的请求方法提供别名,实现通过多种方式发起http请求: axios()、axios.get()、axios.post()
  3. Axios.prototype.getUri根据用户配置生成URL

3、/lib/core/buildFullPath.js

  1. 当requestedURL不是绝对URL时,通过将baseURL与requestedURL相结合来创建新的URL
  2. 如果requestURL是绝对的,则此函数返回requestedURL

4、/lib/core/createError.js

使用指定的消息、配置、错误代码、请求和响应创建错误

5、/lib/core/dispatchRequest.js

dispatchRequest主要做3件事:

  1. 拿到config对象,对config进行传给http请求适配器前的最后处理
  2. http请求适配器根据config配置,发起请求
  3. http请求适配器请求完成后,如果成功则根据header、data、和数据转换器config.transformResponse拿到数据转换后的response,并return

主要过程为:

  • 判断是否进行了取消操作,是即抛出一个Cancel对象
  • 确保headers存在,并对headers进行合并处理,然后删除headers中无用的属性
  • 转换请求或响应的数据
  • 设置适配器,并为适配器设置rejected和fufilled时的方法。http请求适配器会优先使用config上自定义的适配器,没有配置时才会使用默认的XHR或http适配器。Node.js下使用内置的http模块来实现请求发送,在浏览器环境下就使用XMLHttpRequest来实现请求发送

6、/lib/core/enhanceError.js

使用指定的配置、错误代码和响应更新错误

7、/lib/core/InterceptorManager.js

该文件是拦截器构造函数,用来管理拦截器,这个构造函数原型上有3个方法:use、eject、forEach。

  1. 声明handlers数组,用来存放拦截器方法,数组内每一项都是有两个属性的对象,两个属性分别对应成功和失败后执行的函数
  2. 通过use方法往拦截器里添加拦截方法
  3. 通过eject方法注销指定的拦截器,直接将handlers数组的该项设置为null
  4. 通过forEach方法遍历this.handlers,并将this.handlers里的每一项作为参数传给fn方法执行

8、/lib/core/mergeConfig.js

配置特定的合并函数,它通过将两个配置对象合并在一起来创建一个新的配置对象

9、/lib/core/settle.js

基于响应状态resolve或者reject一个Promise

10、/lib/core/transformData.js

使用一个或者一组单例方法转换请求或响应的数据

11、/lib/adapters/http.js

该文件是http请求适配器。在axios中,使用适配器设计模式来屏蔽平台的差异性,让使用者可以在浏览器端和NodeJS环境中使用同一套API发起http请求。httphttp主要用于NodeJS中的请求

12、/lib/adapters/xhr.js

Axios实例的客户端adapter属性默认设置指向文件/adapters/xhr,导出一个方法,即请求的发起 new XMLHttpRequest(),并返回一个Promise。

  1. 如果请求提交的是form表单,则要浏览器去设置Content-Type,"multipart/form-data"属性值
  2. 实例化XMLHttpRequest对象request
  3. 设置 Authorization 头信息
  4. 通过request的open方法初始化一个异步请求,并为request请求设置超时时间、当request的readyState变化时,触发相应的方法、终止请求、请求异常和请求超时时的处理方法
  5. 在标准浏览器环境中运行时,为request添加xsrf标头
  6. 为request请求添加headers,需要时添加withCredentials和responseType属性

13、/lib/cancel/Cancel.js

定义了Cancel类型,当取消请求时抛出一个Cancel对象,并且用一个原型属性__CALCEL__做了标识

14、/lib/cancel/CancelToken.js

  1. axios.CancelToken.source()返回一个对象,其中tokens 属性是 CancelToken 类的实例,cancel 属性是 tokens 内部 promise 的 resolve 触发器
  2. axios 的 config 接受了 CancelToken 类的实例
  3. 当 cancel 触发处于 pending 中的 tokens.promise,取消请求,把 axios 的 promise 走向 rejected 状态

15、/lib/cancel/isCancel.js

用来判断请求是否取消的方法


涛八八
27 声望0 粉丝

下一篇 »
Promiz初探