🚀 原生 AJAX 揭秘:如何使用 XHR 发起请求
🤔 什么是 XHR?
XMLHttpRequest 是浏览器提供的一个内置对象,允许我们在后台与服务器交换数据。这意味着我们可以在不重新加载整个页面的情况下,更新网页的一部分。这就是著名的 AJAX (Asynchronous JavaScript and XML) 技术的核心。
通俗比喻 :
如果把浏览器比作一家餐厅:
- 传统页面刷新:你点完菜,必须离开餐厅,等厨房做好后,再重新进门坐下吃(整个页面重载)。
- XHR (AJAX):你坐在座位上,派服务员(XHR 对象)去厨房催菜或加菜。菜做好了,服务员直接端到你桌上(局部更新),你不需要离开座位。
📂 目录
- [🛠️ 发起请求的标准五步法](#🛠️ 发起请求的标准五步法)
- [💻 代码实战:GET 与 POST](#💻 代码实战:GET 与 POST)
- [📊 核心概念:
readyState状态详解](#📊 核心概念:readyState 状态详解) - [⚠️ 常见陷阱与最佳实践](#⚠️ 常见陷阱与最佳实践)
- [🔄 XHR vs Fetch:该选哪个?](#🔄 XHR vs Fetch:该选哪个?)
- [💡 总结](#💡 总结)
1. 🛠️ 发起请求的标准五步法
使用 XHR 发起一个请求,通常遵循以下五个标准步骤。你可以把它当作一个模板来记忆。
第一步:创建对象
javascript
const xhr = new XMLHttpRequest();
第二步:配置请求
使用 open() 方法初始化请求。
javascript
// open(method, url, async)
xhr.open('GET', 'https://api.example.com/data', true);
method: 请求类型 (GET,POST,PUT等)。url: 请求地址。async: 是否异步(默认为true,强烈建议保持异步,否则会阻塞页面)。
第三步:设置回调(监听状态变化)
在发送之前,先告诉 XHR:"当状态改变时,该做什么"。
javascript
xhr.onreadystatechange = function() {
// 处理逻辑写在这里
};
第四步:发送请求
javascript
xhr.send(); // GET 请求通常传 null 或不传
// xhr.send(data); // POST 请求传入数据
第五步:处理响应
在回调函数中,检查状态码并获取数据。
2. 💻 代码实战:GET 与 POST
场景一:发起 GET 请求
javascript
const xhr = new XMLHttpRequest();
// 1. 配置
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1', true);
// 2. 监听状态
xhr.onreadystatechange = function() {
// readyState === 4 表示请求完成
// status === 200 表示 HTTP 成功
if (xhr.readyState === 4 && xhr.status === 200) {
console.log('请求成功!');
console.log(JSON.parse(xhr.responseText)); // 解析 JSON 数据
} else if (xhr.readyState === 4) {
console.error('请求失败,状态码:', xhr.status);
}
};
// 3. 发送
xhr.send();
场景二:发起 POST 请求(提交表单数据)
POST 请求通常需要设置请求头,并发送数据体。
javascript
const xhr = new XMLHttpRequest();
// 1. 配置
xhr.open('POST', 'https://jsonplaceholder.typicode.com/posts', true);
// 2. 设置请求头(告诉服务器发送的是 JSON 格式)
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
// 3. 监听状态
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 201) { // 201 Created
console.log('创建成功!');
console.log(JSON.parse(xhr.responseText));
}
};
// 4. 发送数据
const data = JSON.stringify({
title: 'Foo',
body: 'Bar',
userId: 1
});
xhr.send(data);
3. 📊 核心概念:readyState 状态详解
xhr.readyState 是一个整数,表示请求当前的阶段。理解它是处理异步逻辑的关键。
| 值 | 状态常量 | 含义 | 说明 |
|---|---|---|---|
| 0 | UNSENT |
未初始化 | 对象已创建,但未调用 open() |
| 1 | OPENED |
已打开 | 已调用 open(),但未调用 send() |
| 2 | HEADERS_RECEIVED |
头已接收 | 已调用 send(),且已接收到响应头 |
| 3 | LOADING |
加载中 | 响应体正在下载中(responseText 已有部分数据) |
| 4 | DONE |
完成 | 整个请求过程结束,数据接收完毕 |
重点 :
我们最关心的是
readyState === 4。只有在这个状态下,xhr.responseText才是完整可用的。
4. ⚠️ 常见陷阱与最佳实践
❌ 陷阱 1:忘记检查 status
只判断 readyState === 4 是不够的。如果服务器返回 404 或 500,readyState 也是 4,但请求实际上是失败的。
javascript
// ✅ 正确写法
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 成功处理
} else {
// 错误处理
}
}
❌ 陷阱 2:回调地狱与代码冗余
如果有多个请求依赖,XHR 的嵌套回调会让代码难以维护(Callback Hell)。
✅ 最佳实践 :
在现代开发中,如果必须用原生 JS,建议将 XHR 封装成 Promise ,或者直接使用 fetch。
javascript
// 封装成 Promise 的简单示例
function request(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = () => {
if (xhr.status === 200) resolve(JSON.parse(xhr.responseText));
else reject(new Error(xhr.statusText));
};
xhr.onerror = () => reject(new Error('Network Error'));
xhr.send();
});
}
// 使用 async/await 调用,代码更清晰
async function getData() {
try {
const data = await request('https://api.example.com/data');
console.log(data);
} catch (error) {
console.error(error);
}
}
❌ 陷阱 3:跨域问题 (CORS)
XHR 同样受浏览器的同源策略限制。如果请求跨域接口,后端必须配置正确的 CORS 头(如 Access-Control-Allow-Origin),否则前端会报错。
5. 🔄 XHR vs Fetch:该选哪个?
| 特性 | XMLHttpRequest (XHR) |
fetch API |
|---|---|---|
| 出现时间 | 古老 (IE5 时代) | 现代 (ES6+) |
| 语法风格 | 基于事件回调 | 基于 Promise |
| 代码简洁度 | 较繁琐 | 简洁优雅 |
| 错误处理 | 需手动检查 status | 网络错误才 reject,HTTP 错误需手动检查 |
| 进度监控 | ✅ 原生支持 (onprogress) |
❌ 需借助 ReadableStream (较复杂) |
| 兼容性 | ✅ 极好 (包括 IE) | ❌ IE 不支持 (需 polyfill) |
建议:
- 新项目 :首选
fetch或axios。- 需要上传进度条 :XHR 依然有优势,或者使用
axios(底层基于 XHR)。- 维护老项目/兼容 IE:必须掌握 XHR。
💡 总结
| 步骤 | 关键代码 | 作用 |
|---|---|---|
| 1. 创建 | new XMLHttpRequest() |
实例化对象 |
| 2. 配置 | xhr.open('GET', url) |
设定方法和地址 |
| 3. 监听 | xhr.onreadystatechange |
绑定状态变化回调 |
| 4. 发送 | xhr.send(body) |
发出请求 |
| 5. 判断 | readyState === 4 && status === 200 |
确认成功并处理数据 |
🚀 博主寄语 :
虽然
fetch是未来,但XHR是过去和现在的桥梁。理解 XHR 的工作原理,能让你更深入地理解 HTTP 请求的生命周期、异步编程模型以及浏览器的网络机制。
记住口诀 :
新建对象 Open 配,
监听状态别嫌累。
Send 发送等回应,
四二零零才到位。
希望这篇文档能帮你彻底搞懂 XHR 请求!如果有疑问,欢迎在评论区留言。👇
喜欢这篇文章吗?记得点赞、收藏、转发哦! ❤️