云计算百科
云计算领域专业知识百科平台

Axios 源码解析:从发起到响应,完整请求链路剖析

在这篇内容,我将拆解 Axios 的整个流程,从发送请求到接收响应数据。整个过程拆成了一条完整的链路,方便大家理解每一步都在干什么。

一、发起请求的两种方式

整个过程的第一步,就是用户通过 Axios 发起一个请求。这里有两种方式:

  • 直接调用 axios() 函数,传入配置对象
  • 调用 axios.get()、axios.post() 这类方法,或者用 axios.create() 创建一个新的实例
  • 不管你用的是哪种方式,最终都会走到同一个地方——createInstance 这个工厂方法。
    在这里插入图片描述

    二、createInstance 工厂方法

    当我们调用 createInstance 的时候,它会去读取我们传入的 config 配置信息。

    在这个过程中,如果你传入了新的配置,比如自定义了 baseURL,那么工厂方法就会把这些新配置和默认配置进行合并覆盖。(第10行)
    在这里插入图片描述
    处理完配置之后,工厂方法就会去调用 Axios.prototype 上的 request 方法——也就是真正干活的那个方法。

    三、request 方法与请求链

    调用 request 方法之后,整个请求就进入了核心处理阶段。request 方法的作用是什么呢?它的核心功能就是串联整个请求链——把请求拦截器、响应拦截器、还有真正的网络请求(dispatchRequest)按顺序串起来。在这里插入图片描述

    它具体是怎么做的呢?它内部有一个数组叫 chain,也就是请求链。request 方法会按照顺序把请求拦截器插入到这个链当中,然后再把 dispatchRequest 也放进去。在这里插入图片描述
    如果你有设置请求拦截器或者响应拦截器的话,它就会在这一步做相应的处理。

    四、请求拦截器

    在请求真正发出去之前,会先进入请求拦截器。
    在请求拦截器里面,我们可能会做这些事情:

    • 把请求头设置得更完整
    • 对请求的数据做一些预处理
    • 比如添加 token、修改 content-type 等等
      在这里插入图片描述在这里插入图片描述
      这一步的目的,就是在请求发出之前,对请求做最后的“加工”。

    注意: 如果添加了多个请求拦截器,它们的执行顺序是后添加的先执行。在request方法构建 chain 数组的时候,会从后往前遍历请求拦截器列表,将每对 [fulfilled, rejected] 用unshift插入到 chain 的头部,所以后添加的请求拦截器会先执行。(也就是三所提到的过程)

    五、transformRequest —— 数据预处理

    请求拦截器处理完之后,进入 dispatchRequest。在 dispatchRequest 内部,会调用transformData()对请求数据进行 transformRequest 转换处理,比如序列化 JSON、设置 Content-Type 等。

    这一步主要做的是什么呢?它会对我们传入的数据进行预处理,比如:

    • 如果我们传的是一个对象,或者是一个 JSON 格式的数据,或者 URL Encoding 格式的数据,那么它就会在请求头里面设置 content-type,告诉浏览器我们传的是什么格式在这里插入图片描述
    • 另外它也可能对数据进行 URL 编码拼接之类的处理

    简单来说,就是让请求数据以正确的格式发送给后端。

    六、dispatchRequest —— 真正发送请求

    数据预处理完成之后,就进入到 dispatchRequest 了。

    但是要注意:真正发送请求的并不是 dispatchRequest 本身。

    dispatchRequest 的作用是什么呢?它主要是做两件事:

  • 最终合并 headers——把之前设置的各种请求头合并到一起

  • 调用 adapter——这个 adapter 才是真正执行网络请求的函数
    在这里插入图片描述

  • 七、adapter —— 根据环境选择请求方式

    那么 adapter 是怎么发送请求的呢?

    在浏览器环境下,它用的是 XMLHttpRequest(也就是 XHR 对象)。在 Node.js 环境下,它会用对应的 HTTP 模块。在这里插入图片描述
    它会根据我们运行的环境来选择合适的 adapter:

    • 如果是在浏览器里运行,就选 XHR
    • 如果是在 Node.js 里运行,就选 Node.js 的 HTTP 模块

    当然,我们也可以通过 adapter 字段自己去手动配置,指定用哪一个。如果我们没有手动配置的话,Axios 就会根据运行环境自动选择合适的 adapter。

    注意,XMLHttpRequest 本身并不是 Promise,是 Axios 的 adapter 把它封装成了 Promise 返回给我们。

    八、请求成功与失败

    当 adapter 发送完请求之后,它会返回一个 Promise 对象。

    这个 Promise 的成功状态叫 fulfilled,失败状态叫 rejected。在这里插入图片描述
    成功的判断标准是什么? 就是返回的 HTTP 状态码必须在 200 到 299 之间,也就是大于等于 200 且小于 300,这个范围才算请求成功。如果不在这个范围之内,那就算失败——可能是网络错误、超时、状态码超出范围等等。在这里插入图片描述
    在这里插入图片描述

    成功之后

    如果请求成功了,就会执行 transformResponse,对响应数据进行转换处理。比如把后端返回的 JSON 字符串转换成 JavaScript 对象,方便我们后续使用。

    失败之后

    如果请求失败了,直接进入 rejected 分支,然后走响应拦截器的 onRejected,或者直接报错。在这里插入图片描述

    九、主动取消请求(特别注意)

    这里有一个特别需要注意的地方——主动取消请求。

    如果我们是主动撤销或者中断一个请求,比如用了 AbortController 来取消请求,那么它会直接进入到 rejected 分支,抛出一个 CancelError 错误。

    关键区别来了:

    • 被动触发的错误(比如网络错误、超时、状态码不对)→ 会进入响应拦截器的失败回调进行处理
    • 主动取消的请求(比如用户手动中断)→ 同样会进入响应拦截器的失败回调,也就是 onRejected 分支,最终抛出一个 CancelError
      在这里插入图片描述
      也就是说,通过CancelToken或 AbortController 主动取消请求时,会进入 adapter 的rejected分支,随后进入响应拦截器的onRejected处理。但如果是在请求拦截器阶段被拒绝,则不会进入响应拦截器。

    十、响应拦截器

    请求发送完成之后,就会进入响应拦截器。

    在响应拦截器里面,我们可以对返回的数据做统一的处理,比如:

    • 对响应数据进行格式化

    • 统一处理错误码

    • 提取真正需要的数据部分在这里插入图片描述
      注意: 如果添加了多个响应拦截器,它们的执行顺序是先添加的先执行。在request方法构建chain数组时,会从前往后遍历响应拦截器列表,将每对 [fulfilled, rejected] 用 push 追加到chain的尾部,所以先添加的响应拦截器会先执行。(和请求拦截器相反的过程)

    十一、请求链的完整顺序

    还记得我们在 request 方法里面说的那个 chain 数组吗?它串联了所有的拦截器和请求流程。

    整个请求链的执行顺序是这样的:

  • 请求拦截器(后添加的先执行)
  • dispatchRequest(真正发请求)
  • 响应拦截器(先添加的先执行)
  • 也就是说,从用户发起请求,到最后拿到结果,整个流程是:在这里插入图片描述

    十二、最终返回给用户

    经过响应拦截器的处理后,最终会得到一个 response 对象,里面包含了:

    • data —— 实际的数据
    • status —— 状态码
    • headers —— 响应头
    • config —— 请求配置
    • 等等
      如果出错了,返回的就是 error 对象。
      在这里插入图片描述
      最后这些东西会传递给我们用户代码里的 .then()、.catch() 或者 try…catch,整个请求流程就结束了。

    总结

    Axios 的整个请求流程可以概括为几个核心节点:

  • 发起请求(两种方式:函数调用 或 方法调用)
  • 工厂方法(合并配置)
  • request 方法(构建请求链)
  • 请求拦截器(预处理请求,后添加的先执行)
  • transformRequest(数据格式转换)
  • dispatchRequest + adapter(真正发送请求)
  • transformResponse(响应数据转换)
  • 响应拦截器(统一处理响应,先添加的先执行)
  • 返回给用户
  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » Axios 源码解析:从发起到响应,完整请求链路剖析
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!