AJAX – 向服务器发送请求
AJAX – 向服务器发送请求(中文讲解)
在 AJAX(Asynchronous JavaScript and XML)中,向服务器发送请求是实现动态数据交互的核心步骤。本教程将详细讲解如何使用 XMLHttpRequest
和 fetch
向服务器发送 AJAX 请求,结合 Node.js、Express 和 MongoDB,展示 GET 和 POST 请求的实际应用,数据格式以 JSON 为主。内容包括步骤、实例、注意事项和最佳实践,力求简洁清晰。
1. AJAX 发送请求概述
- 目的:通过 JavaScript 异步向服务器发送 HTTP 请求(如 GET、POST),获取或提交数据,并更新网页内容。
- 常用工具:
XMLHttpRequest
:传统 AJAX 方法,适合精细控制。fetch
:现代 API,基于 Promise,语法简洁,推荐使用。- 数据格式:通常使用 JSON,服务器返回 JSON 字符串,客户端通过
JSON.parse()
或response.json()
解析。
2. 使用 XMLHttpRequest 发送请求
XMLHttpRequest
是经典的 AJAX 请求方式,适合需要兼容旧浏览器或精细控制的场景。
2.1 步骤
- 创建 XMLHttpRequest 对象:
const xhr = new XMLHttpRequest();
- 配置请求:
使用open(method, url, async)
设置请求方法、URL 和异步标志:
method
:如"GET"
、"POST"
。url
:服务器端点(如"http://localhost:3000/users"
)。async
:true
(异步,推荐)或false
(同步,已弃用)。
xhr.open('GET', 'http://localhost:3000/users', true);
- 设置请求头(可选):
对于 POST 请求,设置Content-Type
:
xhr.setRequestHeader('Content-Type', 'application/json');
- 监听响应:
使用onreadystatechange
处理响应:
readyState=4
:请求完成。status=200
:请求成功。
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
console.log(data);
}
};
- 发送请求:
使用send()
发送,POST 请求可附带数据:
xhr.send(); // GET 请求
// 或
xhr.send(JSON.stringify({ name: "张三" })); // POST 请求
2.2 示例:GET 请求
获取 MongoDB 用户数据:
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);
console.log(users);
} else {
console.error('请求失败:', xhr.status);
}
}
};
xhr.onerror = function () {
console.error('网络错误');
};
xhr.send();
2.3 示例:POST 请求
提交新用户数据:
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) {
console.log('添加成功:', JSON.parse(xhr.responseText));
} else {
console.error('请求失败:', xhr.status);
}
}
};
xhr.send(JSON.stringify({ name: "李四", age: 30 }));
3. 使用 Fetch 发送请求
fetch
是现代 AJAX 的首选,基于 Promise,语法更简洁,推荐用于新项目。
3.1 步骤
- 发送请求:
使用fetch(url, options)
,options
可指定方法、头、请求体等:
fetch('http://localhost:3000/users', {
method: 'GET'
});
- 处理响应:
使用response.json()
解析 JSON 响应:
fetch('http://localhost:3000/users')
.then(response => {
if (!response.ok) throw new Error('网络错误');
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('错误:', error));
- POST 请求:
设置method
和body
:
fetch('http://localhost:3000/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: "李四", age: 30 })
});
3.2 示例:GET 请求(使用 async/await)
async function loadUsers() {
try {
const response = await fetch('http://localhost:3000/users');
if (!response.ok) throw new Error('网络错误');
const users = await response.json();
console.log(users);
} catch (error) {
console.error('错误:', error.message);
}
}
loadUsers();
3.3 示例:POST 请求
async function addUser() {
try {
const response = await fetch('http://localhost:3000/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: "王五", age: 28 })
});
if (!response.ok) throw new Error('网络错误');
const result = await response.json();
console.log('添加成功:', result);
} catch (error) {
console.error('错误:', error.message);
}
}
addUser();
4. 完整实例:AJAX 请求与 MongoDB
以下是一个结合 Node.js、Express 和 MongoDB 的实例,展示如何通过 AJAX 发送 GET 和 POST 请求管理用户数据。
4.1 服务器端(server.js)
const express = require('express');
const { MongoClient } = require('mongodb');
const app = express();
const uri = 'mongodb://localhost:27017/myDatabase';
const client = new MongoClient(uri);
app.use(express.json());
app.use(express.static('public'));
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST');
next();
});
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'));
4.2 客户端(public/index.html)
<!DOCTYPE html>
<html>
<head>
<title>AJAX 请求示例</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()">添加用户(XMLHttpRequest)</button>
<button onclick="addUserFetch()">添加用户(Fetch)</button>
</div>
<button onclick="loadUsers()">加载用户</button>
<pre id="result">点击按钮加载用户数据...</pre>
<script>
// XMLHttpRequest 加载用户
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();
}
// XMLHttpRequest 添加用户
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: ['未知'] }));
}
// Fetch 添加用户
async function addUserFetch() {
const name = document.getElementById('name').value;
const age = parseInt(document.getElementById('age').value);
if (!name || !age) {
alert('请输入姓名和年龄');
return;
}
try {
const response = await fetch('http://localhost:3000/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, age, hobbies: ['未知'] })
});
if (!response.ok) throw new Error('网络错误');
await response.json();
alert('添加成功');
loadUsers();
} catch (error) {
alert('添加失败:' + error.message);
}
}
</script>
</body>
</html>
4.3 MongoDB 数据准备
在 MongoDB 中插入测试数据:
use myDatabase
db.users.insertMany([
{ name: "张三", age: 25, hobbies: ["读书", "旅行"] },
{ name: "李四", age: 30, hobbies: ["编程", "运动"] }
])
4.4 运行和测试
- 启动服务器:
node server.js
- 访问客户端:
- 打开浏览器,访问
http://localhost:3000
。 - 点击“加载用户”,显示用户列表。
- 输入姓名和年龄,点击“添加用户(XMLHttpRequest)”或“添加用户(Fetch)”,添加用户并刷新列表。
5. JSON 在请求中的作用
- 发送请求:POST 请求使用
JSON.stringify()
将数据转为 JSON 字符串(如{ name: "王五", age: 28 }
)。 - 接收响应:服务器返回 JSON 字符串,
XMLHttpRequest
使用JSON.parse()
,fetch
使用response.json()
解析。 - MongoDB:查询结果是 JavaScript 对象,
res.json()
自动转为 JSON 字符串。
6. 注意事项与最佳实践
- 跨域问题:
- 本例使用 CORS(
Access-Control-Allow-Origin: *
)允许跨域。 - 生产环境应限制允许的域名。
- 错误处理:
XMLHttpRequest
:检查readyState
和status
,使用onerror
。fetch
:检查response.ok
,使用try-catch
。
- 超时设置:
XMLHttpRequest
:javascript xhr.timeout = 5000; xhr.ontimeout = () => console.error('请求超时');
fetch
:javascript const controller = new AbortController(); setTimeout(() => controller.abort(), 5000); fetch('http://localhost:3000/users', { signal: controller.signal });
- 安全性:
- 验证用户输入,防止注入。
- 使用 HTTPS 保护数据。
- 推荐 fetch:
fetch
语法更简洁,基于 Promise,适合现代开发。XMLHttpRequest
适用于旧项目或需特殊功能(如上传进度)。
- 调试:
- 使用浏览器开发者工具(Network 面板)检查请求。
- 使用
JSON.stringify(data, null, 2)
格式化输出。
7. 总结
- 发送 AJAX 请求:
XMLHttpRequest
:创建对象、配置请求、发送并处理响应。fetch
:更简洁,推荐使用,基于 Promise。- 实例功能:通过 GET 查询用户,POST 添加用户,结合 MongoDB 和 JSON。
- JSON 角色:请求体和响应使用 JSON 格式,
JSON.stringify()
和JSON.parse()
关键。 - 最佳实践:处理跨域、错误、超时,优先使用
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(express.json());
app.use(express.static('public'));
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST');
next();
});
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 请求示例</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()">添加用户(XMLHttpRequest)</button>
<button onclick="addUserFetch()">添加用户(Fetch)</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: ['未知'] }));
}
async function addUserFetch() {
const name = document.getElementById('name').value;
const age = parseInt(document.getElementById('age').value);
if (!name || !age) {
alert('请输入姓名和年龄');
return;
}
try {
const response = await fetch('http://localhost:3000/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, age, hobbies: ['未知'] })
});
if (!response.ok) throw new Error('网络错误');
await response.json();
alert('添加成功');
loadUsers();
} catch (error) {
alert('添加失败:' + error.message);
}
}
</script>
</body>
</html>