在日常开发中,我们习惯了直接使用 axios.get() 或 axios.post() 来与后端接口进行通信。但你是否真正了解这些操作背后的底层机制?今天我们从最原始的 AJAX 出发,手动实现一个简化版的 Axios,让你彻底搞懂 Axios 是如何工作的!
🧠 一、什么是 AJAX?
AJAX(Asynchronous JavaScript and XML)是一种在 不重新加载页面的情况下,与服务器交换数据并更新部分网页内容 的技术。它的核心是浏览器原生提供的 XMLHttpRequest 对象(简称 XHR)。
🔧 二、Axios 是什么?
Axios 是一个基于 Promise 的 HTTP 库,用于浏览器和 node.js。它对原生 AJAX 做了大量封装,具有如下优势:
• 使用 Promise API(更现代)
• 自动转换 JSON 数据
• 请求/响应拦截器
• 更好的错误处理
• 客户端防止 XSRF
但归根结底,Axios 在浏览器中的底层实现依然基于 XMLHttpRequest。
🧪 三、手写 mini-Axios:底层实现全解析
来看下面这段手写 myAxios 的代码,这是 Axios 底层原理的一个极简实现:
function myAxios(config) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
if (config.params) {
const paramsObj = new URLSearchParams(config.params)
const queryString = paramsObj.toString()
config.url += `?${queryString}`
}
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
if (config.data) {
const jsonStr = JSON.stringify(config.data)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(jsonStr)
} else {
xhr.send()
}
})
}
🧩 四、逐步拆解这段代码的核心点
1️⃣ 参数处理(Query String 拼接)
if (config.params) {
const paramsObj = new URLSearchParams(config.params)
const queryString = paramsObj.toString()
config.url += `?${queryString}`
}
这是对 GET 请求中 params 的拼接封装,等价于 axios.get('/api/user', { params: { id: 1 } })。
2️⃣ 请求初始化
xhr.open(config.method || 'GET', config.url)
利用 XMLHttpRequest 的 open 方法初始化请求方法和 URL。
3️⃣ 监听请求结束
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
• loadend 事件在请求完成后(不管成功失败)都会触发。
• 判断状态码是否为成功范围(200~299),来决定是否 resolve 或 reject。
• 对返回的 JSON 字符串进行解析,模仿 Axios 的行为。
4️⃣ 请求体处理
if (config.data) {
const jsonStr = JSON.stringify(config.data)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(jsonStr)
} else {
xhr.send()
}
• data 用于 POST / PUT 等请求时,传递请求体数据。
• 设置 Content-Type 为 application/json,表明这是 JSON 请求。
• 如果没有数据,直接发送空请求体。
⚖️ 五、自定义的myAxios 与 axios 有哪些不同?
特性 | myAxios | Axios |
---|---|---|
Promise 支持 | ✅ | ✅ |
请求方式封装 | ❌ 手动传参 | ✅ axios.get/post等 |
拦截器 | ❌ | ✅ |
错误分类处理 | 简单错误处理 | ✅ 状态码封装+错误对象丰富 |
超时控制 | ❌ | ✅ |
请求取消 | ❌ | ✅(CancelToken) |
🏁 六、总结:掌握原理,才能自由使用
通过这次手写 myAxios,你不仅掌握了 Axios 的核心封装思想,还更深入地理解了 AJAX 的工作机制。无论是面试中的手写题,还是调试实际问题时,了解这一套逻辑都会让你比别人更从容。
💡 如果你觉得有帮助:
• 点个赞 👍 鼓励一下
• 关注我,后续继续出系列文章:
• 手写Promise原理
• 实现一个简易Vue响应式系统
• 从0到1写一个前端路由