先行知识
注意可能因为版本不同,导致源码的某些细节不一致,但是只要设计思路是一致的就不会有太割裂的改动。
另外在源码分析中只会聚焦于实现某一目的的相关代码,不会贴出全部代码。这样更加精简也便于理解。
XMLHttpRequest和Fetch
XMLHttpRequest是一个早期的浏览器 API,用于执行异步请求。
兼容性:XHR 在所有现代浏览器中都得到了支持,并且对于旧版浏览器的支持要比 fetch 好。
事件处理:XHR 提供了一个基于事件的接口,可以监听多个事件,如 progress、error、load 等。
状态信息:XHR 在请求过程中提供了更多的状态信息,例如可以通过 readyState 属性了解请求的当前状态。
复杂性:XHR 的 API 相对较老,使用起来比较繁琐,需要处理状态变化、事件监听等。
可读性:XHR 的代码往往不够直观,尤其是在处理错误和异步逻辑时。
JSON支持:XHR 不直接支持 JSON,需要手动将响应文本转换为 JSON。
Fetch 是一个现代的、基于 Promise 的 API,用于替代 XMLHttpRequest。
Promise 语法: fetch 使用 Promise,这使得异步代码更容易编写和理解。
语法简洁: 提供了一个更为简洁和直观的 API。
流式数据:支持流式数据,可以在数据到达时逐块处理,而不必等待全部数据。
默认异步:默认就是异步的,不需要额外的设置。
更好的 JSON 支持:直接将响应解析为 JSON。
兼容性:在旧版浏览器中可能不被支持(往往实际中的打包会做降级处理)。
默认不发送或接收 cookies: 除非明确设置。
没有timeout:需要手写代码
文件结构
- adapters/:适配器文件夹,用于存放适配器处理文件
i. xhr.js - core/:核心业务文件夹
i. Axios.js
ii. dispatchRequest.js
iii. interceptorManager.js - helper/:辅助用文件夹,存放工具函数
- axios.js:对外暴露的实例化入口,使用了工厂设计模式来创建实例
- defaults.js:Axios类的初始化配置内容
- utils.js:常用的工具函数
adapters/xhr.js 分析
对XMLHttpRequest进行封装,实现一个xhr的适配器文件。
返回一个promise,函数参数为config配置对象。
在这个返回的promise中进行XMLHttpRequest的请求处理。
export default function xhrAdapter(config) {
let xhr_promise = new Promise(function dispatchXhrRequest(resolve, reject) {
let request = new XMLHttpRequest(); // XMLHttpRequest的请求
request.open(config.method.toUpperCase(), config.url, true);
request.send(config.data)
let responseData = request.responseText;
resolve(response);
request = null
}
return xhr_promise
}
构建一个axios的默认配置对象
包含适配器和其他请求内容,用于给axios实例化时使用。对应文件为./defaults.js
import utils from './utils'
function getDefaultAdapter() {
let adapter = require('./adapters/xhr').default;
return adapter
}
let defaults = {
adapter: getDefaultAdapter(),
transformRequest: [],
transformResponse: [
function transformResponse(data) {
if (typeof data === 'string') {
try {
data = JSON.parse(data);}
catch (error) {
console.log(error)}
}
return data
}
],
timeout: 5000,
xsrfCookieName: 'XSRF-TOKEN', //xsrfCookieName 表示存储 token 的 cookie 名称
xsrfHeaderName: 'X-XSRF-TOKEN',