手写AJAX请求:从XMLHttpRequest到fetch的封装,打造自己的请求库
🧑🏫 作者:全栈老李
📅 更新时间:2025 年 6 月
🧑💻 适合人群:前端初学者、进阶开发者
🚀 版权:本文由全栈老李原创,转载请注明出处。
大家好,我是全栈老李。今天咱们聊聊前端工程师的必修课——AJAX请求封装。这玩意儿就像厨师的刀工,看起来基础,但用好了能让你在项目里游刃有余。
为什么需要自己封装请求库?
现在前端请求库多如牛毛,axios、umi-request、fetch...那为啥还要自己封装?这就好比问"有外卖为啥还要学做饭"——当你的项目遇到特殊需求(比如统一错误处理、自定义重试机制),现成的库可能就不够灵活了。
举个真实案例:去年我们团队接了个物联网项目,设备上报数据需要特殊的内容类型处理,还要在请求头带动态token。用axios改配置很麻烦,最后我们直接基于fetch封装了一套,代码量少了30%。
从石器时代到现代:AJAX进化史
1. 上古神器 XMLHttpRequest
这是浏览器最早的AJAX实现,现在很多老项目还在用。它的API设计...怎么说呢,就像用算盘写代码:
function requestByXHR(url) {
// 全栈老李提示:注意事件监听要放在open之前
const xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log('老李提醒:成功拿到数据', xhr.responseText)
} else {
console.error('出错了老铁', xhr.status)
}
}
}
xhr.send()
}
这种回调地狱写法,让当年多少前端工程师头秃。不过现在面试还经常问,毕竟能考察对异步的理解。
2. 现代武器 fetch API
ES6带来的fetch清爽多了,基于Promise的链式调用真香:
fetch('/api/data')
.then(response => {
if (!response.ok) throw new Error('网络响应不正常')
return response.json()
})
.then(data => console.log('全栈老李提示:数据在这里 →', data))
.catch(error => console.error('抓到一个错误:', error))
但fetch有两个坑:
- 默认不会带cookie(需要配置credentials)
- 错误处理比较迷——只有网络错误才会reject,HTTP 404/500反而会resolve
打造你的专属请求库
下面我们实现一个支持以下特性的请求库:
✅ 统一错误处理