封装 `getJSON` 函数:使用 AJAX 实现 Promise 风格的 JSON 请求

40 阅读2分钟

本文基于一段完整的 HTML 代码,展示如何将传统的 XMLHttpRequest(AJAX)封装为一个支持 PromisegetJSON 函数。通过该函数,可以以更现代、简洁的方式发起异步请求并处理响应数据。


完整 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),包含 resolvereject 两个参数。

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 === 4status === 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() 消费)。

结语

虽然现代开发中推荐使用 fetchaxios,但理解如何将传统 AJAX 封装为 Promise,有助于深入掌握 JavaScript 异步机制的本质。本示例展示了如何用原生技术实现现代化的异步编程风格,是学习前端进阶的重要一步。