AJAX – 创建 XMLHttpRequest 对象

AJAX – 创建 XMLHttpRequest 对象(中文讲解)

XMLHttpRequest 是 AJAX 的核心技术,用于在浏览器中发送异步 HTTP 请求与服务器交互。以下是关于如何创建和使用 XMLHttpRequest 对象的详细中文讲解,涵盖创建步骤、基本用法、在 Node.js 和 MongoDB 环境中的应用,以及与 JSON 的结合,力求简洁清晰。


1. 什么是 XMLHttpRequest?

  • 定义XMLHttpRequest 是浏览器提供的 JavaScript API,用于发送 HTTP 请求(如 GET、POST)并接收服务器响应,允许异步更新网页内容。
  • 用途:常用于 AJAX 场景,如动态加载数据、提交表单等。
  • 与 JSON 的关系XMLHttpRequest 通常处理 JSON 格式的响应数据,通过 JSON.parse() 解析。

2. 创建 XMLHttpRequest 对象

在浏览器中,创建 XMLHttpRequest 对象非常简单,直接使用其构造函数:

const xhr = new XMLHttpRequest();
  • 说明
  • XMLHttpRequest 是浏览器内置对象,无需额外引入。
  • 创建后,xhr 是一个对象实例,可用于配置和发送请求。

3. 使用 XMLHttpRequest 的步骤

以下是使用 XMLHttpRequest 的标准流程:

  1. 创建对象
   const xhr = new XMLHttpRequest();
  1. 配置请求
    使用 open(method, url, async) 方法初始化请求:
  • method:HTTP 方法(如 "GET""POST")。
  • url:目标 URL(如 "http://localhost:3000/data")。
  • async:是否异步(true 表示异步,false 表示同步,推荐 true)。
   xhr.open('GET', 'http://localhost:3000/users', true);
  1. 设置请求头(可选)
    如果需要发送 JSON 数据或设置其他头:
   xhr.setRequestHeader('Content-Type', 'application/json');
  1. 处理响应
    使用 onreadystatechange 或其他事件监听器处理响应:
  • readyState:请求状态(0-4,4 表示完成)。
  • status:HTTP 状态码(如 200 表示成功)。
   xhr.onreadystatechange = function () {
     if (xhr.readyState === 4 && xhr.status === 200) {
       const data = JSON.parse(xhr.responseText); // 解析 JSON 响应
       console.log(data);
     }
   };
  1. 发送请求
    使用 send() 方法发送请求,POST 请求可附带数据:
   xhr.send(); // GET 请求
   // 或
   xhr.send(JSON.stringify({ name: "张三" })); // POST 请求

4. 完整实例:使用 XMLHttpRequest 加载用户数据

以下是一个完整的 AJAX 实例,结合 Node.js、Express 和 MongoDB,使用 XMLHttpRequest 从服务器获取用户数据。

4.1 服务器端(Node.js + Express + MongoDB)

创建 server.js,从 MongoDB 查询用户并返回 JSON:

const express = require('express');
const { MongoClient } = require('mongodb');
const app = express();
const uri = 'mongodb://localhost:27017/myDatabase';
const client = new MongoClient(uri);

// 允许跨域
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST');
  next();
});

// 提供静态文件
app.use(express.static('public'));

// 查询用户
app.get('/users', async (req, res) => {
  try {
    await client.connect();
    const db = client.db('myDatabase');
    const collection = db.collection('users');
    const users = await collection.find({}).toArray();
    res.json(users);
  } catch (error) {
    console.error('查询失败:', error);
    res.status(500).json({ error: '服务器错误' });
  } finally {
    await client.close();
  }
});

app.listen(3000, () => console.log('服务器运行在 http://localhost:3000'));
  • 说明
  • /users 端点返回 MongoDB 中的用户数据(JSON 格式)。
  • CORS 头允许跨域请求。
  • public 文件夹托管客户端 HTML。

4.2 客户端(HTML + XMLHttpRequest)

public 文件夹中创建 index.html

<!DOCTYPE html>
<html>
<head>
  <title>AJAX XMLHttpRequest 示例</title>
  <style>
    pre { font-size: 16px; background: #f4f4f4; padding: 10px; }
    button { padding: 10px 20px; margin-bottom: 10px; }
  </style>
</head>
<body>
  <h1>用户查询</h1>
  <button onclick="loadUsers()">加载用户</button>
  <pre id="result">点击按钮加载用户数据...</pre>
  <script>
    function loadUsers() {
      const xhr = new XMLHttpRequest();
      xhr.open('GET', 'http://localhost:3000/users', true);
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            const users = JSON.parse(xhr.responseText);
            document.getElementById('result').innerText = JSON.stringify(users, null, 2);
          } else {
            document.getElementById('result').innerText = '错误:请求失败';
          }
        }
      };
      xhr.onerror = function () {
        document.getElementById('result').innerText = '错误:网络错误';
      };
      xhr.send();
    }
  </script>
</body>
</html>
  • 说明
  • 点击“加载用户”按钮,创建 XMLHttpRequest 对象,发送 GET 请求。
  • 监听 onreadystatechange,当 readyState=4status=200 时,解析 JSON 响应。
  • 使用 JSON.parse()xhr.responseText 转为对象,显示在页面。

4.3 MongoDB 数据准备

在 MongoDB 中创建测试数据:

use myDatabase
db.users.insertMany([
  { name: "张三", age: 25, hobbies: ["读书", "旅行"] },
  { name: "李四", age: 30, hobbies: ["编程", "运动"] }
])
  • 预期响应
  [
    {
      "_id": "someObjectId1",
      "name": "张三",
      "age": 25,
      "hobbies": ["读书", "旅行"]
    },
    {
      "_id": "someObjectId2",
      "name": "李四",
      "age": 30,
      "hobbies": ["编程", "运动"]
    }
  ]

5. 运行和测试

  1. 启动服务器
   node server.js
  1. 访问客户端
  • 打开浏览器,访问 http://localhost:3000
  • 点击“加载用户”按钮,页面显示 MongoDB 查询到的用户数据(JSON 格式)。
  • 检查开发者工具(F12,Network 面板)确认请求成功。

6. 扩展:POST 请求添加用户

6.1 更新服务器代码

server.js 中添加 POST 端点:

app.use(express.json()); // 解析 JSON 请求体

app.post('/users', async (req, res) => {
  try {
    await client.connect();
    const db = client.db('myDatabase');
    const collection = db.collection('users');
    const user = req.body;
    const result = await collection.insertOne(user);
    res.json({ message: '添加成功', id: result.insertedId });
  } catch (error) {
    console.error('添加失败:', error);
    res.status(500).json({ error: '服务器错误' });
  } finally {
    await client.close();
  }
});

6.2 更新客户端代码

修改 index.html,添加表单和 POST 请求:

<!DOCTYPE html>
<html>
<head>
  <title>AJAX XMLHttpRequest 示例</title>
  <style>
    pre { font-size: 16px; background: #f4f4f4; padding: 10px; }
    button, input { padding: 10px; margin: 5px; }
  </style>
</head>
<body>
  <h1>用户管理</h1>
  <div>
    <input id="name" placeholder="姓名">
    <input id="age" type="number" placeholder="年龄">
    <button onclick="addUser()">添加用户</button>
  </div>
  <button onclick="loadUsers()">加载用户</button>
  <pre id="result">点击按钮加载用户数据...</pre>
  <script>
    function loadUsers() {
      const xhr = new XMLHttpRequest();
      xhr.open('GET', 'http://localhost:3000/users', true);
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            const users = JSON.parse(xhr.responseText);
            document.getElementById('result').innerText = JSON.stringify(users, null, 2);
          } else {
            document.getElementById('result').innerText = '错误:请求失败';
          }
        }
      };
      xhr.onerror = function () {
        document.getElementById('result').innerText = '错误:网络错误';
      };
      xhr.send();
    }

    function addUser() {
      const name = document.getElementById('name').value;
      const age = parseInt(document.getElementById('age').value);
      if (!name || !age) {
        alert('请输入姓名和年龄');
        return;
      }
      const xhr = new XMLHttpRequest();
      xhr.open('POST', 'http://localhost:3000/users', true);
      xhr.setRequestHeader('Content-Type', 'application/json');
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            alert('添加成功');
            loadUsers(); // 刷新列表
          } else {
            alert('添加失败');
          }
        }
      };
      xhr.send(JSON.stringify({ name, age, hobbies: ['未知'] }));
    }
  </script>
</body>
</html>
  • 说明
  • addUser() 创建 XMLHttpRequest,发送 POST 请求,包含 JSON 数据。
  • 使用 JSON.stringify() 将用户数据转为 JSON 字符串。
  • 成功后刷新用户列表。

7. 注意事项与最佳实践

  1. 跨域问题
  • 本例使用 CORS 允许跨域(Access-Control-Allow-Origin: *)。
  • 生产环境中,限制允许的域名以提高安全性。
  1. 错误处理
  • 检查 xhr.readyStatexhr.status
  • 使用 xhr.onerror 捕获网络错误。
  1. 异步 vs 同步
  • 始终设置 async=truexhr.open(..., true)),避免阻塞浏览器。
  • 同步请求(async=false)已弃用,可能导致界面卡顿。
  1. JSON 解析
  • 使用 try-catch 确保 JSON.parse() 安全:
    javascript try { const data = JSON.parse(xhr.responseText); } catch (error) { console.error('JSON 解析错误:', error.message); }
  1. 现代替代
  • 推荐使用 fetch API,语法更简洁,基于 Promise:
    javascript fetch('http://localhost:3000/users').then(response => response.json());
  • XMLHttpRequest 仍适用于旧项目或需精细控制的场景。
  1. 调试
  • 使用浏览器开发者工具(Network 面板)检查请求和响应。
  • 验证 JSON 格式(JSONLint)。

8. 总结

  • 创建 XMLHttpRequest:使用 new XMLHttpRequest(),通过 opensetRequestHeadersend 配置和发送请求。
  • 实例功能:通过 AJAX 获取和添加 MongoDB 用户数据,使用 JSON 格式交互。
  • 与 JSONXMLHttpRequest 接收 JSON 字符串,JSON.parse() 解析为对象,JSON.stringify() 用于 POST 数据。
  • 优势:支持所有 HTTP 方法,适合复杂 AJAX 场景。
  • 局限性:代码较繁琐,现代开发推荐 fetch

如果你需要更复杂的功能(如文件上传、分页查询),或想转换到 fetch,请告诉我,我会提供详细代码或指导!

const express = require('express');
const { MongoClient } = require('mongodb');
const app = express();
const uri = 'mongodb://localhost:27017/myDatabase';
const client = new MongoClient(uri);

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST');
  next();
});

app.use(express.json());
app.use(express.static('public'));

app.get('/users', async (req, res) => {
  try {
    await client.connect();
    const db = client.db('myDatabase');
    const collection = db.collection('users');
    const users = await collection.find({}).toArray();
    res.json(users);
  } catch (error) {
    console.error('查询失败:', error);
    res.status(500).json({ error: '服务器错误' });
  } finally {
    await client.close();
  }
});

app.post('/users', async (req, res) => {
  try {
    await client.connect();
    const db = client.db('myDatabase');
    const collection = db.collection('users');
    const user = req.body;
    const result = await collection.insertOne(user);
    res.json({ message: '添加成功', id: result.insertedId });
  } catch (error) {
    console.error('添加失败:', error);
    res.status(500).json({ error: '服务器错误' });
  } finally {
    await client.close();
  }
});

app.listen(3000, () => console.log('服务器运行在 http://localhost:3000'));
<!DOCTYPE html>
<html>
<head>
  <title>AJAX XMLHttpRequest 示例</title>
  <style>
    pre { font-size: 16px; background: #f4f4f4; padding: 10px; }
    button, input { padding: 10px; margin: 5px; }
  </style>
</head>
<body>
  <h1>用户管理</h1>
  <div>
    <input id="name" placeholder="姓名">
    <input id="age" type="number" placeholder="年龄">
    <button onclick="addUser()">添加用户</button>
  </div>
  <button onclick="loadUsers()">加载用户</button>
  <pre id="result">点击按钮加载用户数据...</pre>
  <script>
    function loadUsers() {
      const xhr = new XMLHttpRequest();
      xhr.open('GET', 'http://localhost:3000/users', true);
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            const users = JSON.parse(xhr.responseText);
            document.getElementById('result').innerText = JSON.stringify(users, null, 2);
          } else {
            document.getElementById('result').innerText = '错误:请求失败';
          }
        }
      };
      xhr.onerror = function () {
        document.getElementById('result').innerText = '错误:网络错误';
      };
      xhr.send();
    }

    function addUser() {
      const name = document.getElementById('name').value;
      const age = parseInt(document.getElementById('age').value);
      if (!name || !age) {
        alert('请输入姓名和年龄');
        return;
      }
      const xhr = new XMLHttpRequest();
      xhr.open('POST', 'http://localhost:3000/users', true);
      xhr.setRequestHeader('Content-Type', 'application/json');
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            alert('添加成功');
            loadUsers();
          } else {
            alert('添加失败');
          }
        }
      };
      xhr.send(JSON.stringify({ name, age, hobbies: ['未知'] }));
    }
  </script>
</body>
</html>

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注