axios源码

两个流程参考图

一个是我写的 【Xmind思维导图】axios源码
axios源码

一个是.学长写的 【Xmind思维导图】Axios https://app.xmind.cn/share/oWnkR6z1?xid=4ubuXhXS

官方文档

lec飞书资源

来自 .学长

数据流

axios 作为方法导出,接收 defaults 默认配置

axios 自带 .create 方法,用户在二次封装时用到,传入一个 config 配置对象

两个方法通过 createInstance 被创造,不过 .create 方法传入的是 (mergeConfig(defaults, config)) 深合并后的默认配置

createInstance 方法中,首先创建一个 Axios 实例(即 context),然后定义一个 instance 函数,将 instance 内部的 request 方法的 this 指向 context(Axios) 实例,所以 instance(config) 等价于 Axios.request(config);

并使用 extend 浅拷贝将 context(Axios) 将实例上的所有属性方法都拷贝到 instance 方法上,最终实现:

  • axios(config) 等价于 axios.request(config)

  • axios.get / axios.post 等可用

  • axios.defaults / axios.interceptors 可访问

接着看 Axios 类,内部的方法主要分刚才的 request(核心) 和 get/put/post 等请求方法,请求方法内部会调用 request

request 方法接收两个参数 url,config,但一般情况下我们只传入一个参数(url || 配置对象),都会作为 url 来被传入,所以 request 内部的第一个逻辑就是判断 url/config 并归位;

第二步,创建一个 Promise 执行链(chain),初始值为 [dispatchRequest, undefined];dispatchRequest是一个函数,内部调用 xhr,负责发起请求

第三步,从 this.interceptors.request/response 中获取请求/响应拦截器,以 [onFulfilled,onRejected] 的形式插入到 chain 链的首/尾端 (请求拦截器插到开头,响应插到末尾)

第四步,使用 while 遍历 chain 链,取出拦截器配置,使用 promise 处理

最后,return promise

有关 dispatchRequest 方法,内部分三步

第一步是调用 processConfig 对配置进行标准化处理(如合并 baseURL + url,规范化 headers,转换 data 等);

第二步 xhr 适配处理,传入 config,并返回一个 Promise

第三步当适配器 resolve 响应后,使用 transformResponse 对响应数据进行转换(如解析 JSON)

最后构造最终的 response 对象并 resolve

有关 xhr 方法

第一步先解构出 url / data / headers / method / responseType / timeout 五个变量

第二步实例化一个 XMLHttpRequest 对象为 request

第三步判断 responseType / timeout 是否存在,如果存在就直接赋值到 request

第四步调用 request 的 open 方法,传入 method / url / 异步:true,在传入 method 的同时将 method 值转为大写

第五步遍历 headers 的所有属性,如果 data 为 null 且属性名为 content-type 则删除 headers 的属性名,否则处理 headers 赋值给 request

内部还实现的三个方法

request 的 onerror,reject

request 的 ontimeout,reject

request 的 onreadystatechange (readyState发生变化时自动调用),先判断 readyState 的值非 4 return,4 则继续进行(请求已完成),接着看 status 为 0 则 return (网络错误/跨域失败/取消请求),非 0 继续,这时取出所有头信息,接着处理响应数据 Data,设定完最终 response 后就可以 resolve 了