尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

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

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响应数据转换响应拦截器统一处理响应先添加的先执行返回给用户
返回列表