《getJSON》

55 阅读2分钟

从 0 到 1 实现 getJSON 方法:深入理解 XMLHttpRequest 与现代请求方案

亲手实现一个基于XMLHttpRequestgetJSON方法,能帮我们更透彻理解网络请求的底层逻辑。

一、 getJSON

const getJSON = (url) => new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.send();

  xhr.onreadystatechange = () => {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
        try {
          const data = JSON.parse(xhr.responseText);
          resolve(data);
        } catch (err) {
          reject(`JSON解析失败:${err.message}`);
        }
      } else {
        reject(`请求失败:状态码${xhr.status}`);
      }
    }
  };

  //  监听网络错误(如断网、跨域拦截)
  xhr.onerror = () => {
    reject('网络请求失败,请检查网络连接');
  };
});

getJSON('https://api.github.com/users/shunwuyu')
  .then(data => console.log('用户数据:', data))
  .catch(err => console.error('请求出错:', err));

二、核心 API 解析

实现getJSON的关键是理解XMLHttpRequest的四个核心成员:

  1. readyState表示请求的生命周期状态,共 5 个值:

    • 0:未初始化(open未调用)
    • 1:已打开(open已调用,send未调用)
    • 2:已发送(send已调用,响应头已接收)
    • 3:加载中(正在接收响应体)
    • 4:完成(响应体完全接收)我们只在readyState === 4时处理响应,因为此时数据才完整。
  2. onreadystatechange监听readyState变化的事件回调,每次状态改变都会触发。正因为它会多次触发,所以必须通过readyState === 4过滤无效状态。

  3. responseText存储服务器返回的响应体文本,对于 JSON 请求,需要用JSON.parse转换为 JavaScript 对象。注意这里可能出现解析错误,必须用try/catch捕获。

  4. onerror专门处理网络层面的错误(如断网、域名无法解析),这类错误不会触发onreadystatechange,需要单独监听。

三、与 fetch 的对比

// fetch版本
const fetchJSON = (url) => 
  fetch(url)
    .then(response => {
      if (!response.ok) throw new Error(`状态码${response.status}`);
      return response.json();
    });

// 使用方式相同
fetchJSON('https://api.github.com/users/shunwuyu')
  .then(data => console.log(data))
  .catch(err => console.error(err));

四、为什么要学 XMLHttpRequest?

虽然fetch更简洁,但理解XMLHttpRequest有重要意义:

  1. 掌握底层原理:理解fetch的设计思路来源
  2. 兼容旧环境:部分老旧系统仍需支持 IE
  3. 精细化控制:XMLHttpRequest提供更细粒度的状态监听(如上传进度)
  4. 问题排查:遇到请求异常时,能从底层分析原因

总结

通过实现getJSON,我们不仅获得了一个实用的工具函数,更深入理解了浏览器网络请求的底层机制。XMLHttpRequest虽然语法相对繁琐,但它的状态管理、错误处理设计,为现代请求 API 提供了重要参考。

在实际开发中,推荐优先使用fetch或成熟库(如 axios),但亲手实现一次getJSON,会让你对网络请求的理解更上一层楼。