长轮询是一种服务器推送技术,它允许服务器在数据可用时立即向客户端推送数据,而不是让客户端频繁地发送请求。本文将详细介绍长轮询的实现原理,并提供客户端和服务端的代码示例。
工作原理
- 客户端发送一个请求到服务器
- 服务器保持连接打开,直到有新数据可用
- 当有新数据时,服务器立即响应客户端
- 客户端收到响应后,立即发送新的请求
- 这个过程不断重复
服务端实现(Node.js + Express)
javascript
const express = require("express");
const app = express();
// 存储所有等待响应的客户端
let clients = [];
// 模拟数据更新
function updateData() {
const newData = {
timestamp: new Date().toISOString(),
message: "服务器有新数据",
};
// 向所有等待的客户端发送数据
clients.forEach((client) => {
client.res.json(newData);
});
// 清空客户端列表
clients = [];
}
// 每10秒更新一次数据
setInterval(updateData, 10000);
// 长轮询端点
app.get("/long-polling", (req, res) => {
// 将客户端添加到等待列表
clients.push({
id: Date.now(),
res: res,
});
// 设置超时(30秒)
setTimeout(() => {
const index = clients.findIndex((client) => client.res === res);
if (index !== -1) {
clients.splice(index, 1);
res.json({ message: "请求超时" });
}
}, 30000);
});
app.listen(3000, () => {
console.log("服务器运行在 http://localhost:3000");
});
客户端实现(JavaScript)
javascript
async function longPolling() {
try {
const response = await fetch("http://localhost:3000/long-polling");
const data = await response.json();
// 处理接收到的数据
console.log("收到新数据:", data);
// 立即发起新的请求
longPolling();
} catch (error) {
console.error("长轮询错误:", error);
// 发生错误时,等待一段时间后重试
setTimeout(longPolling, 5000);
}
}
// 开始长轮询
longPolling();
优点
- 实时性好:服务器可以立即推送数据
- 减少请求次数:相比传统轮询,减少了不必要的请求
- 实现简单:不需要特殊的协议或库
- 兼容性好:可以在任何支持 HTTP 的环境中运行
缺点
- 服务器资源消耗:需要保持连接打开
- 超时处理:需要处理连接超时的情况
- 扩展性:当并发连接数增加时,服务器压力较大
使用场景
- 实时通知系统
- 聊天应用
- 实时数据更新
- 简单的实时监控系统
注意事项
- 需要正确处理连接超时
- 考虑服务器的并发连接数限制
- 实现错误重试机制
- 注意内存泄漏问题