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
的标准流程:
- 创建对象:
const xhr = new XMLHttpRequest();
- 配置请求:
使用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);
- 设置请求头(可选):
如果需要发送 JSON 数据或设置其他头:
xhr.setRequestHeader('Content-Type', 'application/json');
- 处理响应:
使用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);
}
};
- 发送请求:
使用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=4
且status=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. 运行和测试
- 启动服务器:
node server.js
- 访问客户端:
- 打开浏览器,访问
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. 注意事项与最佳实践
- 跨域问题:
- 本例使用 CORS 允许跨域(
Access-Control-Allow-Origin: *
)。 - 生产环境中,限制允许的域名以提高安全性。
- 错误处理:
- 检查
xhr.readyState
和xhr.status
。 - 使用
xhr.onerror
捕获网络错误。
- 异步 vs 同步:
- 始终设置
async=true
(xhr.open(..., true)
),避免阻塞浏览器。 - 同步请求(
async=false
)已弃用,可能导致界面卡顿。
- JSON 解析:
- 使用
try-catch
确保JSON.parse()
安全:javascript try { const data = JSON.parse(xhr.responseText); } catch (error) { console.error('JSON 解析错误:', error.message); }
- 现代替代:
- 推荐使用
fetch
API,语法更简洁,基于 Promise:javascript fetch('http://localhost:3000/users').then(response => response.json());
XMLHttpRequest
仍适用于旧项目或需精细控制的场景。
- 调试:
- 使用浏览器开发者工具(Network 面板)检查请求和响应。
- 验证 JSON 格式(JSONLint)。
8. 总结
- 创建 XMLHttpRequest:使用
new XMLHttpRequest()
,通过open
、setRequestHeader
、send
配置和发送请求。 - 实例功能:通过 AJAX 获取和添加 MongoDB 用户数据,使用 JSON 格式交互。
- 与 JSON:
XMLHttpRequest
接收 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>