JavaScript中实现长轮询的核心思路是:客户端发起HTTP请求后,服务器保持连接打开直至有新数据或超时才响应;客户端收到响应后立即发起下一次请求,形成“请求-等待-响应-再请求”循环,从而减少无效请求、提升实时性。

JavaScript 中实现长轮询(Long Polling)的核心思路是:发起一个 HTTP 请求,服务器不立即返回响应,而是保持连接打开,直到有新数据或超时才返回;客户端收到响应后立刻发起下一次请求,形成“请求-等待-响应-再请求”的循环。
长轮询的基本实现逻辑
与普通轮询不同,长轮询减少了无效请求次数。服务器端需支持挂起响应(如 Node.js 的 Express、Koa 或后端其他语言的对应机制),前端则用 fetch 或 XMLHttpRequest 发起请求,并在响应到达后立即重连。
- 每次请求都应带唯一标识(如时间戳或序列号),便于服务端识别和去重
- 必须设置合理的超时时间(如 30 秒),防止连接无限挂起
- 需处理网络中断、5xx 错误、CORS 等异常,失败后应指数退避重试
使用 fetch 实现长轮询的示例代码
以下是一个简洁可靠的长轮询客户端实现:
let isRunning = true;
async function longPoll() {
if (!isRunning) return;
try {
const res = await fetch('/api/updates', {
method: 'GET',
headers: { 'Accept': 'application/json' },
// 避免缓存
cache: 'no-cache'
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
console.log('收到更新:', data);
} catch (err) {
console.warn('长轮询请求失败:', err.message);
// 可加入退避策略,比如延迟 1–5 秒后再试
} finally {
// 响应处理完立刻发起下一次请求(模拟“长连接”效果)
if (isRunning) setTimeout(longPoll, 0);
}
}
// 启动
longPoll();
// 停止轮询(例如页面卸载时)
window.addEventListener('beforeunload', () => {
isRunning = false;
});
服务端配合要点(以 Express 为例)
前端要真正“长轮询”,后端不能一收到请求就立刻返回。需要暂存请求,在有数据或超时时才响应:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
- 维护一个待通知队列(如用数组或 Map 存储 pending response 对象)
- 当新数据到达(如通过 WebSocket、数据库监听、消息队列等触发),遍历队列并发送响应
- 每个请求设超时(如
req.socket.setTimeout(30000)),超时后主动 end 响应 - 注意并发控制和内存泄漏:及时清理已断开连接的 pending 请求
与 SSE、WebSocket 的对比和选型建议
长轮询是兼容性最好的实时方案(支持所有 HTTP 环境),但不如现代方案高效:
- SSE(Server-Sent Events):单向推送,轻量、原生支持重连,适合服务端→客户端广播场景(如通知、日志流)
- WebSocket:全双工、低延迟、高并发,适合聊天、协作编辑等双向强交互场景
- 长轮询:无特殊协议要求,代理/CDN/旧浏览器友好,适合中小规模、低频更新(如订单状态轮询、配置变更同步)
如果项目已支持现代浏览器,优先考虑 SSE;若需双向通信且可控部署环境,WebSocket 更合适;仅需简单兜底或兼容老旧系统时,长轮询仍是实用选择。

















