【前端三剑客-17/Lesson31(2025-11-12)】Ajax 数据请求详解:从原理到手写实现🌐

39 阅读5分钟

🌐在现代 Web 开发中,Ajax(Asynchronous JavaScript and XML) 是实现网页局部刷新、提升用户体验的核心技术之一。尽管名字中含有 “XML”,但如今它更多用于处理 JSON 格式的数据。本文将深入剖析 Ajax 的工作原理、完整流程、关键属性与方法,并提供手写 Ajax 请求的详细示例,帮助你彻底掌握这一前端必备技能。


⚙️ 什么是 Ajax?

Ajax 全称是 Asynchronous JavaScript and XML,但它并不局限于 XML——如今绝大多数 Ajax 请求都使用 JSON(JavaScript Object Notation) 作为数据交换格式,因其更轻量、更易解析。

Ajax 的核心思想是:在不重新加载整个页面的情况下,通过 JavaScript 向服务器发送请求并接收响应,从而动态更新页面内容。这种“异步”通信机制极大地提升了 Web 应用的交互性和性能。


🔁 Ajax 的基本工作流程

要使用原生 JavaScript 实现一个完整的 Ajax 请求,需遵循以下标准流程:

1. 🧱 实例化 XMLHttpRequest 对象

const xhr = new XMLHttpRequest();

XMLHttpRequest 是浏览器内置的构造函数,用于创建一个 Ajax 请求对象。这是所有操作的起点。

💡 注意:虽然名字叫 XMLHttpRequest,但它完全可以处理 JSON、文本、HTML 等多种格式。


2. 🔓 调用 open() 方法配置请求

xhr.open(method, url, async);
  • method:HTTP 请求方法,如 'GET''POST''PUT''DELETE' 等。
  • url:请求的目标地址(可以是相对路径或绝对 URL)。
  • async:是否异步执行,默认为 true(强烈建议保持异步,避免阻塞 UI)。

例如:

xhr.open('GET', '/api/users', true);

3. 📤 调用 send() 方法发送请求

xhr.send(body);
  • 对于 GET 请求,通常传入 null 或省略参数,因为数据通过 URL 传递。
  • 对于 POST/PUT 请求,可在此处传入请求体(如 JSON 字符串、表单数据等)。

示例(POST):

xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({ name: 'Alice', age: 25 }));

⚠️ 注意:若需发送 JSON 数据,务必设置正确的 Content-Type 请求头。


4. 👂 监听请求状态变化:onreadystatechange

Ajax 是异步的,因此不能直接获取响应结果。我们需要监听 readyState 的变化:

xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    // 请求成功完成
    const data = JSON.parse(xhr.responseText);
    console.log(data);
  }
};

✅ 关键判断条件:

  • readyState === 4:请求已完成(详见下文状态码说明)
  • status === 200:HTTP 状态码为 200,表示成功

📊 readyState 状态详解

XMLHttpRequest 对象的 readyState 属性表示当前请求的阶段,共有 5 个值:

状态说明
0UNSENTXMLHttpRequest 对象已创建,但尚未调用 open()
1OPENEDopen() 已被调用,连接已建立
2HEADERS_RECEIVEDsend() 已被调用,响应头和状态码已收到
3LOADING正在接收响应体(可能部分数据已可用)
4DONE整个请求过程完成,响应数据全部接收完毕

📌 只有当 readyState === 4 时,才能安全地读取 responseTextresponse


📡 HTTP 状态码(status)

xhr.status 返回服务器的 HTTP 状态码,常见值包括:

  • 200:OK,请求成功
  • 201:Created,资源创建成功(常用于 POST)
  • 400:Bad Request,客户端请求错误
  • 401:Unauthorized,未认证
  • 403:Forbidden,无权限
  • 404:Not Found,资源不存在
  • 500:Internal Server Error,服务器内部错误

✅ 判断成功通常用 xhr.status >= 200 && xhr.status < 300 更严谨,因为 201、204 等也属于成功。


🧩 解析响应数据:JSON.parse()

服务器返回的数据通常是字符串形式(即使看起来像对象),需手动解析:

const data = JSON.parse(xhr.responseText);
  • xhr.responseText:以字符串形式返回响应体。
  • 若服务器返回非 JSON(如纯文本),则无需解析。

⚠️ 如果响应不是合法 JSON,JSON.parse() 会抛出错误!建议加 try-catch:

try {
  const data = JSON.parse(xhr.responseText);
} catch (e) {
  console.error('JSON 解析失败:', e);
}

✍️ 手写一个完整的 Ajax 函数

结合以上知识,我们可以封装一个通用的 Ajax 函数:

function ajax(options) {
  const { method = 'GET', url, data = null, success, error } = options;

  const xhr = new XMLHttpRequest();

  // 配置请求
  xhr.open(method.toUpperCase(), url, true);

  // 设置请求头(仅对 POST/PUT 等有 body 的请求)
  if (data && typeof data === 'object') {
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify(data));
  } else {
    xhr.send();
  }

  // 监听状态变化
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
        let response;
        try {
          response = JSON.parse(xhr.responseText);
        } catch (e) {
          response = xhr.responseText; // 非 JSON 响应
        }
        success && success(response);
      } else {
        error && error(`请求失败: ${xhr.status}`);
      }
    }
  };
}

// 使用示例
ajax({
  method: 'POST',
  url: '/api/login',
  data: { username: 'admin', password: '123456' },
  success: (res) => console.log('登录成功', res),
  error: (msg) => console.error(msg)
});

🛑 注意事项与最佳实践

  1. 跨域问题:Ajax 默认受同源策略限制。若需跨域,服务器必须配置 CORS(Access-Control-Allow-Origin)。
  2. 安全性:不要在前端暴露敏感接口或密钥;使用 HTTPS 防止中间人攻击。
  3. 错误处理:除了 status,还应监听 onerror 事件处理网络错误:
    xhr.onerror = function() {
      console.error('网络错误');
    };
    
  4. 现代替代方案:虽然原生 Ajax 是基础,但实际开发中更推荐使用 fetch API 或 Axios,它们基于 Promise,语法更简洁。

🎯 总结

Ajax 是前端与后端通信的基石技术。掌握其核心流程——实例化 → open → send → 监听 onreadystatechange → 判断 readyState 和 status → 解析响应——不仅能应对面试题,更能深入理解 Web 数据交互的本质。

尽管现代框架(如 React、Vue)和工具(如 Axios)简化了网络请求,但手写原生 Ajax 依然是检验前端基本功的重要标准。只有理解底层机制,才能在复杂场景中游刃有余。

✅ 会读 Ajax?不够!
✅ 会手写 Ajax?这才是真功夫!


📚 延伸学习建议

  • 学习 fetch API 与 Ajax 的对比
  • 了解 WebSocket 与 Ajax 的适用场景差异
  • 探索如何用 Ajax 实现文件上传、进度条等功能

现在,你已经拥有了从零实现 Ajax 的全部知识!去动手试试吧!🚀