🥇 Axios

链接:http://www.axios-js.com/
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
安装:npm install axios
尚硅谷_axios从入门到源码分析.doc

🥇 特性

从浏览器中创建 XMLHttpRequests
从 node.js 创建 http 请求
支持 Promise API
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换 JSON 数据
支持批量发送多个请求
客户端支持防御 XSRF

🥇 前后台交互的基本过程

  1. 1. 前后应用从浏览器端向服务器发送HTTP请求(请求报文)
  2. 2. 后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
  3. 3. 浏览器端接收到响应, 解析显示响应体/调用监视回调

🥇 HTTP 请求报文

  1. 1. 请求行: 请求方式/url
  2. 2. 多个请求头: 一个请求头由name:value组成, Host/Cookie/Content-Type
  3. 3. 请求体

🥇 HTTP 响应报文

  1. 1. 响应行: 响应状态码/对应的文本
  2. 2. 多个响应头: Content-Type / Set-Cookie
  3. 3. 响应体

🥇 url 上的 2 种请求参数

  1. query 参数:
  2. 路由path: /xxx
  3. 请求path: /xxx?username=xxx&password=yyy
  4. 获取参数: req.query.username / req.query.password
  5. params 参数:
  6. 路由path: /xxx/:username/:password
  7. 请求path: /xxx/xxx/123
  8. 获取参数: req.params.username / req.params.password

🥇 常见响应状态码

  1. 200 OK 请求成功。一般用于GETPOST请求
  2. 201 Created 已创建。成功请求并创建了新的资源
  3. 401 Unauthorized 未授权/请求要求用户的身份认证
  4. 404 Not Found 服务器无法根据客户端的请求找到资源
  5. 500 Internal Server Error 服务器内部错误,无法完成请求

🥇 不同类型的请求及其作用:

  1. 1. GET: 从服务器端读取数据
  2. 2. POST: 向服务器端添加新数据
  3. 3. PUT: 更新服务器端已经数据
  4. 4. DELETE: 删除服务器端数据

🥇 API 的分类

  1. 1. REST API: restful
  2. 发送请求进行CRUD哪个操作由请求方式来决定,增删改查(CRUD
  3. 同一个请求路径可以进行多个操作
  4. 请求方式会用到GET/POST/PUT/DELETE
  5. 2. REST API: restless
  6. 请求方式不决定请求的CRUD操作,增删改查(CRUD
  7. 一个请求路径只对应一个操作
  8. 一般只有GET/POST
  9. 测试: 可以使用 json-server 快速搭建模拟的 rest api 接口

🥇 axios 的特点

基于 promise 的封装 XHR 的异步 ajax 请求库
浏览器端 node 端,都可以使用
支持请求/响应拦截器
支持请求取消
请求/响应数据转换
批量发送多个请求

🥇 axios 返回值解析

config - 请求配置
data - 响应体, 返回结果 ( 返回结果会自动解析 json 数据为一个对象 )
headers - 相应头信息
request - 原生的 AJAX 请求对象
status - 响应的状态码
statusText - 响应的字符串
image.png

🥇 axios 常用语法以及使用

🥈 请求配置

这些是创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method,请求将默认使用 get 方法。

  1. {
  2. // url 是用于请求的服务器 URL
  3. url: '/user',
  4. // method 是创建请求时使用的方法
  5. method: 'get',
  6. /**
  7. * 如果没有配置 method 默认就是 get
  8. * method 常见的可选值为 get / post / put / delete
  9. */
  10. // baseURL 将自动加在 url 前面,除非 url 是一个绝对 URL
  11. // 比如这里的请求地址就是: https://www.baidu.com/api/user
  12. // 它可以通过设置一个 baseURL 便于为 axios 实例的方法传递相对 URL
  13. baseURL: 'https://www.baidu.com/api/',
  14. // transformRequest 允许在向服务器发送前,修改请求数据
  15. // 只能用在 PUT, POST 和 PATCH 这几个请求方法
  16. // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  17. transformRequest: [function (data, headers) {
  18. // 对 data 进行任意转换处理
  19. return data;
  20. }],
  21. // transformResponse 在传递给 then/catch 前,允许修改响应数据
  22. transformResponse: [function (data) {
  23. // 对 data 进行任意转换处理
  24. return data;
  25. }],
  26. // headers 是即将被发送的自定义请求头
  27. headers: {'X-Requested-With': 'XMLHttpRequest'},
  28. headers: {'Content-Type':'application/x-www-form-urlencoded'},
  29. headers: {'Content-Type':'multipart/form-data'}
  30. // paramsSerializer 是一个负责 params 序列化的函数
  31. // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  32. paramsSerializer: function(params) {
  33. return Qs.stringify(params, {arrayFormat: 'brackets'})
  34. },
  35. // params 是即将与请求一起发送的 URL 参数
  36. // params 是添加到 url 的请求字符串中的,用于 get 请求。
  37. // 必须是一个无格式对象 (plain object) 或 URLSearchParams 对象
  38. params: {
  39. ID: 12345
  40. },
  41. // data 是作为请求主体被发送的数据
  42. // data 是添加到请求体(body)中的, 用于post请求。
  43. // 只适用于这些请求方法 PUT, POST, 和 PATCH
  44. // 在没有设置 transformRequest 时,必须是以下类型之一:
  45. // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  46. // - 浏览器专属:FormData, File, Blob
  47. // - Node 专属: Stream
  48. data: {
  49. name: 'chen'
  50. },
  51. // timeout 指定请求超时的毫秒数 (0 表示无超时时间)
  52. // 如果请求话费了超过 timeout 的时间,请求将被中断
  53. timeout: 1000,
  54. // withCredentials 表示跨域请求时是否需要使用凭证
  55. withCredentials: false, // default
  56. // adapter 允许自定义处理请求,以使测试更轻松
  57. // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
  58. adapter: function (config) {
  59. /* ... */
  60. },
  61. // auth 表示应该使用 HTTP 基础验证,并提供凭据
  62. // 这将设置一个 Authorization 头,覆写掉现有的任意使用 headers 设置的自定义 Authorization 头
  63. auth: {
  64. username: 'janedoe',
  65. password: 's00pers3cret'
  66. },
  67. // responseType 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  68. responseType: 'json', // default:json
  69. // responseEncoding 表示用于解码响应的编码
  70. // 注意:忽略 "responseType" 或客户端请求的 "responseType"
  71. responseEncoding: 'utf8', // default:utf8
  72. // xsrfCookieName 是用作 xsrf token 的值的 cookie 的名称
  73. xsrfCookieName: 'XSRF-TOKEN', // default:XSRF-TOKEN
  74. // xsrfHeaderName 是携带 xsrf 令牌值的 http 标头的名称
  75. xsrfHeaderName: 'X-XSRF-TOKEN', // default:X-XSRF-TOKEN
  76. // onUploadProgress 允许为上传处理进度事件
  77. onUploadProgress: function (progressEvent) {
  78. // 使用本机进度事件做任何你想做的事
  79. },
  80. // onDownloadProgress 允许为下载处理进度事件
  81. onDownloadProgress: function (progressEvent) {
  82. // 对原生进度事件的处理
  83. },
  84. // maxContentLength 定义允许的响应内容的最大尺寸
  85. maxContentLength: 2000,
  86. // validateStatus 定义对于给定的 HTTP 响应状态码是 resolve 或 reject promise 。如果 validateStatus 返回 true (或者设置为 null 或 undefined ),promise 将被 resolve; 否则,promise 将被 rejecte
  87. validateStatus: function (status) {
  88. return status >= 200 && status < 300; // default
  89. },
  90. // maxRedirects 定义在 node.js 中 follow 的最大重定向数目
  91. // 如果设置为0,将不会 follow 任何重定向
  92. maxRedirects: 5, // default
  93. // socketPath 定义了一个在 node.js 中使用的 UNIX 套接字。
  94. // 例如 '/var/run/docker.sock' 向 docker 守护进程发送请求。
  95. // 只能指定 socketPath 或 proxy。
  96. // 如果两者都指定,则使用 socketPath。
  97. socketPath: null, // default
  98. // httpAgent 和 httpsAgent 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
  99. // keepAlive 默认没有启用
  100. httpAgent: new http.Agent({ keepAlive: true }),
  101. httpsAgent: new https.Agent({ keepAlive: true }),
  102. // proxy 定义代理服务器的主机名称和端口
  103. // auth 表示 HTTP 基础验证应当用于连接代理,并提供凭据
  104. // 这将会设置一个 Proxy-Authorization 头,覆写掉已有的通过使用 header 设置的自定义 Proxy-Authorization 头。
  105. proxy: {
  106. host: '127.0.0.1',
  107. port: 9000,
  108. auth: {
  109. username: 'mikeymike',
  110. password: 'rapunz3l'
  111. }
  112. },
  113. // cancelToken 指定用于取消请求的 cancel token
  114. cancelToken: new CancelToken(function (cancel) {
  115. })
  116. }

🥈 请求

  1. // 通用请求
  2. axios({
  3. method: "GET", // 请求方式
  4. url: "http://localhost:3000/student", // URL
  5. params: { // url 后的参数
  6. ID: 12345
  7. },
  8. }).then((response) => {
  9. console.log(response);
  10. });
  11. // 发送 GET 请求(默认的方法)
  12. axios(url);
  13. // 请求方法的别名
  14. // 为方便起见, 为所有支持的请求方法提供了别名
  15. // axios.request(config)
  16. // axios.get(url[, config])
  17. // axios.delete(url[, config])
  18. // axios.head(url[, config])
  19. // axios.options(url[, config])
  20. // axios.post(url[, data[, config]])
  21. // axios.put(url[, data[, config]])
  22. // axios.patch(url[, data[, config]])
  23. axios.[请求方式](
  24. [url],
  25. { [data] },
  26. { [config] }
  27. ).then((response) => {}).catch((err) => {});

🥈 配置默认值

  1. // 设置默认配置
  2. axios.defaults.method = "GET"; // 设置默认的请求类型为 GET
  3. axios.defaults.baseURL = 'http://www.baidu.com'; // 设置基础请求 url
  4. axios.defaults.timeout = 2000; // 设置默认请求的超时时间
  5. axios({
  6. url: '/user/00001'
  7. }).then((response) => {}).catch((err) => {});

🥈 创建实例

  1. // 可以使用自定义配置新建一个 axios 实例
  2. // axios.create([config])
  3. const instance = axios.create({
  4. baseURL: 'https://www.baidu.com/api/',
  5. timeout: 1000,
  6. headers: {'X-Custom-Header': 'foobar'}
  7. });
  8. instance.get(url[, config]);
  9. // 有多个不同域名的时候就创建多个实例, 配置不同的参数

🥈 拦截器

在请求或响应被 then 或 catch 处理前拦截它们。

  1. // 拦截器必须放在请求之前要不然不生效
  2. // 添加请求拦截器
  3. axios.interceptors.request.use(
  4. function (config) {
  5. // 在发送请求之前做些什么
  6. console.log(config);
  7. console.log("请求之前");
  8. return config;
  9. },
  10. function (error) {
  11. // 对请求错误做些什么
  12. console.log("请求失败");
  13. return Promise.reject(error);
  14. }
  15. );
  16. // 添加响应拦截器
  17. axios.interceptors.response.use(
  18. function (response) {
  19. // 对响应数据做点什么
  20. console.log(response);
  21. console.log("响应成功");
  22. return response;
  23. },
  24. function (error) {
  25. // 对响应错误做点什么
  26. console.log("响应失败");
  27. return Promise.reject(error);
  28. }
  29. );
  30. // 创建的实例拦截器
  31. const instance = axios.create({...});
  32. // 添加实例请求拦截器
  33. instance.interceptors.request.use(...);
  34. // 添加实例响应拦截器
  35. instance.interceptors.response.use(...);
  36. // 移除拦截器
  37. const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
  38. axios.interceptors.request.eject(myInterceptor);

🥈 并发

  1. axios.all(iterable)
  2. axios.spread(callback)
  3. axios.all(
  4. [
  5. axios.get("/test1"),
  6. axios.get("/test2")
  7. ]
  8. ).then(
  9. axios.spread((test1Res, test2Res) => {
  10. console.log(test1Res, test2Res);
  11. })
  12. );

🥇 axios 源码分析

🥈 源码难点与流程分析

  1. 1. axiosAxios的关系
  2. axios函数对应的是Axios.prototype.request方法通过bind(Axiox的实例)产生的函数
  3. axiosAxios原型上的所有发特定类型请求的方法: get()/post()/put()/delete()
  4. axiosAxios的实例上的所有属性: defaults/interceptors
  5. 后面又添加了create()/CancelToken()/all()
  6. 2. axios.create()返回的对象与axios的区别
  7. 1). 相同:
  8. 都是一个能发任意请求的函数: request(config)
  9. 都有发特定请求的各种方法: get()/post()/put()/delete()
  10. 都有默认配置和拦截器的属性: defaults/interceptors
  11. 2). 不同:
  12. 默认匹配的值不一样
  13. instance没有axios后面添加的一引起方法: create()/CancelToken()/all()
  14. 3. axios发请求的流程
  15. 1). 整体流程: request(config) ===> dispatchRequest(config) ===> xhrAdapter(config)
  16. 2). request(config): 将请求拦截器 / dispatchRequest() / 响应拦截器 通过promise链串连起来, 返回promise
  17. 3). dispatchRequest(config): 转换请求数据 ===> 调用xhrAdapter()发请求 ===> 请求返回后转换响应数据. 返回promise
  18. 4). xhrAdapter(config): 创建XHR对象, 根据config进行相应设置, 发送特定请求, 并接收响应数据, 返回promise
  19. 4. axios的请求/响应拦截器是什么?
  20. 1). 请求拦截器: 在真正发请求前, 可以对请求进行检查或配置进行特定处理的函数,
  21. 包括成功/失败的函数, 传递的必须是config
  22. 2). 响应拦截器: 在请求返回后, 可以对响应数据进行特定处理的函数,
  23. 包括成功/失败的函数, 传递的默认是response
  24. 5. axios的请求/响应数据转换器是什么?
  25. 1). 请求转换器: 对请求头和请求体数据进行特定处理的函数
  26. setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
  27. return JSON.stringify(data)
  28. 2). 响应转换器: 将响应体json字符串解析为js对象或数组的函数
  29. response.data = JSON.parse(response.data)
  30. 6. response的整体结构
  31. {
  32. data,
  33. status,
  34. statusText,
  35. headers,
  36. config,
  37. request
  38. }
  39. 7. error的整体结构
  40. {
  41. message,
  42. request,
  43. response
  44. }
  45. 8. 如何取消未完成的请求
  46. 1).当配置了cancelToken对象时, 保存cancel函数
  47. 创建一个用于将来中断请求的cancelPromise
  48. 并定义了一个用于取消请求的cancel函数
  49. cancel函数传递出来
  50. 2.调用cancel()取消请求
  51. 执行cacel函数, 传入错误信息message
  52. 内部会让cancelPromise变为成功, 且成功的值为一个Cancel对象
  53. cancelPromise的成功回调中中断请求, 并让发请求的proimse失败, 失败的reasonCacel对象

🥈 axios 源码分析 - 源码目录结构

  1. ├── /dist/ # 项目输出目录
  2. ├── /lib/ # 项目源码目录
  3. ├── /adapters/ # 定义请求的适配器 xhrhttp
  4. ├── http.js # 实现http适配器(包装http包)
  5. └── xhr.js # 实现xhr适配器(包装xhr对象)
  6. ├── /cancel/ # 定义取消功能
  7. ├── /core/ # 一些核心功能
  8. ├── Axios.js # axios的核心主类
  9. ├── dispatchRequest.js # 用来调用http请求适配器方法发送请求的函数
  10. ├── InterceptorManager.js # 拦截器的管理器
  11. └── settle.js # 根据http响应状态,改变Promise的状态
  12. ├── /helpers/ # 一些辅助方法
  13. ├── axios.js # 对外暴露接口
  14. ├── defaults.js # axios的默认配置
  15. └── utils.js # 公用工具
  16. ├── package.json # 项目信息
  17. ├── index.d.ts # 配置TypeScript的声明文件
  18. └── index.js # 入口文件

🥈 axios 与 Axios 的关系

  1. 1.从语法上来说: axios 不是 Axios 的实例
  2. 2.从功能上来说: axios Axios 的实例
  3. 3.axios Axios.prototype.request 函数 bind() 返回的函数
  4. 4.axios 作为对象有 Axios 原型对象上的所有方法, Axios 对象上所有属性

🥈 instance 与 axios 的区别

  1. 1.相同:
  2. (1)都是一个能发任意请求的函数: request(config)
  3. (2)都有发特定请求的各种方法: get()/post()/put()/delete()
  4. (3)都有默认配置和拦截器的属性: defaults/interceptors
  5. 2.不同:
  6. (1)默认匹配的值很可能不一样
  7. (2)instance没有axios后面添加的一些方法: create()/CancelToken()/all()

🥈 axios 运行的整体流程

image.png

  1. 1.整体流程:
  2. request(config) ==> dispatchRequest(config) ==> xhrAdapter(config)
  3. 2.request(config):
  4. 将请求拦截器 / dispatchRequest() / 响应拦截器 通过promise链串连起来, 返回promise
  5. 3.dispatchRequest(config):
  6. 转换请求数据 ===> 调用xhrAdapter()发请求 ===> 请求返回后转换响应数据. 返回promise
  7. 4.xhrAdapter(config):
  8. 创建XHR对象, 根据config进行相应设置, 发送特定请求, 并接收响应数据, 返回promise

🥈 axios 的请求/响应拦截器是什么

image.png

  1. 1.请求拦截器:
  2. 在真正发送请求前执行的回调函数
  3. 可以对请求进行检查或配置进行特定处理
  4. 成功的回调函数, 传递的默认是config(也必须是)
  5. 失败的回调函数, 传递的默认是error
  6. 2.响应拦截器
  7. 在请求得到响应后执行的回调函数
  8. 可以对响应数据进行特定处理
  9. 成功的回调函数, 传递的默认是response
  10. 失败的回调函数, 传递的默认是error

🥈 axios 的请求/响应数据转换器是什么

  1. 1.请求转换器: 对请求头和请求体数据进行特定处理的函数
  2. if (utils.isObject(data)) {
  3. setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
  4. return JSON.stringify(data);
  5. }
  6. 2.响应转换器: 将响应体json字符串解析为js对象或数组的函数
  7. response.data = JSON.parse(response.data)

🥈 response 的整体结构

  1. {
  2. data,
  3. status,
  4. statusText,
  5. headers,
  6. config,
  7. request
  8. }

🥈 error 的整体结构

  1. {
  2. message,
  3. response,
  4. request,
  5. }

🥈 如何取消未完成的请求

  1. 1.当配置了cancelToken对象时, 保存cancel函数
  2. (1)创建一个用于将来中断请求的cancelPromise
  3. (2)并定义了一个用于取消请求的cancel函数
  4. (3)将cancel函数传递出来
  5. 2.调用cancel()取消请求
  6. (1)执行cacel函数, 传入错误信息message
  7. (2)内部会让cancelPromise变为成功, 且成功的值为一个Cancel对象
  8. (3)在cancelPromise的成功回调中中断请求, 并让发请求的proimse失败, 失败的reasonCacel对象

🥇 axios 二次封装

🥈 二次封装规则

  1. 1). 统一进行请求配置
  2. 2). 请求过程中 loading 提示
  3. 3). 请求体参数以 urlencoded 形式传递
  4. urlencoded 格式,又叫 form 格式、x-www-form-urlencoded 格式
  5. 它是一种表单格式
  6. 组成格式
  7. 键值对组成
  8. 键和值之间用 = name=poloyy
  9. 多个键值对之间用 & 隔开:name=poloyy&age=19
  10. 4). 请求成功的 value 不再是 response, 而是 response.data
  11. 5). 请求失败统一进行提示处理, 每个请求不需要单独处理

🥈 二次封装的常用设置

  1. import axios from 'axios';
  2. // 创建一个 axios 实例
  3. const requests = axios.create({
  4. baseURL: 'https://localhost:8000/api/', // 设置基础请求 url 地址
  5. timeout: 1000, // 设置默认请求的超时时间
  6. });
  7. // 添加请求拦截器
  8. requests.interceptors.request.use(
  9. function (config) {
  10. // 在发送请求之前做些什么
  11. console.log("请求之前", config);
  12. return config;
  13. },
  14. function (error) {
  15. // 对请求错误做些什么
  16. console.log("请求失败");
  17. return Promise.reject(error);
  18. }
  19. );
  20. // 添加响应拦截器
  21. requests.interceptors.response.use(
  22. function (response) {
  23. // 对响应数据做点什么
  24. console.log("响应成功", response);
  25. return response.data;
  26. },
  27. function (error) {
  28. // 对响应错误做点什么
  29. console.log("响应失败");
  30. return Promise.reject(error);
  31. }
  32. );
  33. export default requests