原生 AJAX 揭秘:如何使用 XHR 发起请求

🚀 原生 AJAX 揭秘:如何使用 XHR 发起请求

🤔 什么是 XHR?

XMLHttpRequest 是浏览器提供的一个内置对象,允许我们在后台与服务器交换数据。这意味着我们可以在不重新加载整个页面的情况下,更新网页的一部分。这就是著名的 AJAX (Asynchronous JavaScript and XML) 技术的核心。

通俗比喻

如果把浏览器比作一家餐厅:

  • 传统页面刷新:你点完菜,必须离开餐厅,等厨房做好后,再重新进门坐下吃(整个页面重载)。
  • XHR (AJAX):你坐在座位上,派服务员(XHR 对象)去厨房催菜或加菜。菜做好了,服务员直接端到你桌上(局部更新),你不需要离开座位。

📂 目录

  1. [🛠️ 发起请求的标准五步法](#🛠️ 发起请求的标准五步法)
  2. [💻 代码实战:GET 与 POST](#💻 代码实战:GET 与 POST)
  3. [📊 核心概念:readyState 状态详解](#📊 核心概念:readyState 状态详解)
  4. [⚠️ 常见陷阱与最佳实践](#⚠️ 常见陷阱与最佳实践)
  5. [🔄 XHR vs Fetch:该选哪个?](#🔄 XHR vs Fetch:该选哪个?)
  6. [💡 总结](#💡 总结)

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)

建议

  • 新项目 :首选 fetchaxios
  • 需要上传进度条 :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 请求!如果有疑问,欢迎在评论区留言。👇

喜欢这篇文章吗?记得点赞、收藏、转发哦! ❤️

相关推荐
ZC跨境爬虫1 小时前
跟着 MDN 学 HTML day_34:(深入XML 中的 CDATASection 接口)
xml·前端·html·html5·媒体
之歆1 小时前
DAY_20JavaScript 条件语句与循环结构深度学习(二)
前端·javascript
山北雨夜漫步1 小时前
LangGraph
java·前端·算法
漓漾li1 小时前
每日面试题-前端
前端·react.js·面试
布局呆星1 小时前
Vue3 路由守卫详解:全局守卫、路由独享守卫、组件内守卫
前端·javascript·vue.js
小李子呢02111 小时前
前端八股Vue---ref操作 DOM 元素或组件,调用子组件方法
前端·javascript·vue.js
Yoram2 小时前
Vue3 响应性:跨上下文的传递、转换与作用域控制
前端·vue.js
掘金安东尼2 小时前
开源小工具:掘金福利页「补签卡」按次数自动兑换(Chrome 扩展)
前端·开源
Mike_jia2 小时前
Sirius Scan:开源漏洞扫描利器,重塑企业安全防护体系
前端