本文基于一段完整的 HTML 代码,展示如何将传统的 XMLHttpRequest(AJAX)封装为一个支持 Promise 的 getJSON 函数。通过该函数,可以以更现代、简洁的方式发起异步请求并处理响应数据。
完整 HTML 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const getJSON = (url) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
resolve(data);
}
};
xhr.onerror = function () {
reject('出错了');
};
});
};
getJSON("https://api.github.com/users/shunwuyu")
.then((data) => {
console.log(data);
})
.catch(err => {
console.log(err);
});
</script>
</body>
</html>
核心逻辑解析
1. 定义 getJSON 函数
const getJSON = (url) => {
return new Promise((resolve, reject) => { ... });
};
getJSON是一个接收 URL 参数的箭头函数;- 它返回一个
Promise实例,这是 ES6 提供的异步编程解决方案; Promise构造函数接收一个执行器函数(executor),包含resolve和reject两个参数。
2. 使用 XMLHttpRequest 发起请求
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.send();
- 创建
XMLHttpRequest对象; - 配置为异步 GET 请求;
- 发送请求。
3. 监听响应状态
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
resolve(data);
}
};
- 当
readyState === 4且status === 200时,表示请求成功完成; - 使用
JSON.parse()将返回的 JSON 字符串解析为 JavaScript 对象; - 调用
resolve(data)将数据传递给.then()方法。
4. 错误处理
xhr.onerror = function () {
reject('出错了');
};
- 监听网络错误事件;
- 若发生错误,调用
reject()触发.catch()回调。
5. 使用方式:链式调用 .then() 和 .catch()
getJSON("https://api.github.com/users/shunwuyu")
.then((data) => {
console.log(data);
})
.catch(err => {
console.log(err);
});
- 调用
getJSON返回的 Promise 实例; - 成功时执行
.then()中的回调; - 失败时执行
.catch()中的回调。
与 Fetch API 的对比
| 特性 | AJAX(XMLHttpRequest) | Fetch |
|---|---|---|
| 异步实现 | 基于回调函数 | 基于 Promise |
| 代码复杂度 | 较高,需手动管理状态 | 简洁,语法清晰 |
| 数据格式 | 需手动解析 JSON | 可直接调用 .json() |
| 错误捕获 | 需监听 onerror | 自动进入 .catch() |
✅ fetch 更简单易用,无需手动处理回调嵌套;而 AJAX 仍可通过封装提升可读性。
封装要点总结
- ✅ 使用
new Promise()将异步操作包装为可链式调用的 Promise; - ✅ 在
resolve()中传入解析后的 JSON 数据; - ✅ 通过
reject()处理错误; - ✅ 支持
.then()和.catch()链式调用; - ✅ 实现了“thennable”行为(即能被
.then()消费)。
结语
虽然现代开发中推荐使用 fetch 或 axios,但理解如何将传统 AJAX 封装为 Promise,有助于深入掌握 JavaScript 异步机制的本质。本示例展示了如何用原生技术实现现代化的异步编程风格,是学习前端进阶的重要一步。