js comet实现
Comet 实现方法
Comet 是一种基于 HTTP 长连接的服务器推送技术,允许服务器实时向客户端推送数据。以下是几种常见的 Comet 实现方式:
长轮询(Long Polling)
客户端发送请求后,服务器保持连接打开直到有新数据或超时。数据返回后客户端立即发起新请求。
function longPolling() {
fetch('/comet-endpoint')
.then(response => response.json())
.then(data => {
console.log('Received:', data);
longPolling(); // 立即发起新请求
})
.catch(error => {
console.error('Error:', error);
setTimeout(longPolling, 5000); // 错误时延迟重试
});
}
永久帧(Forever Frame)
隐藏 iframe 保持与服务器的持久连接,服务器通过 script 标签推送数据。
<iframe id="cometFrame" src="/comet-endpoint" style="display:none"></iframe>
服务器响应格式:
<script>parent.handlePush(data);</script>
Server-Sent Events (SSE)
HTML5 标准协议,使用 EventSource API 建立单向服务器推送通道。
const eventSource = new EventSource('/comet-endpoint');
eventSource.onmessage = (event) => {
console.log('New message:', event.data);
};
eventSource.onerror = () => {
console.error('SSE error');
};
WebSocket
全双工通信协议,适合需要双向实时通信的场景。
const socket = new WebSocket('wss://example.com/comet');
socket.onmessage = (event) => {
console.log('Message:', event.data);
};
socket.onopen = () => {
socket.send('Client ready');
};
服务器端实现示例(Node.js)
使用 Express 实现长轮询:
const express = require('express');
const app = express();
const clients = [];
app.get('/comet', (req, res) => {
clients.push(res); // 存储响应对象
req.on('close', () => {
clients.splice(clients.indexOf(res), 1); // 清理断开连接
});
});
function pushData(data) {
clients.forEach(res => {
res.json(data); // 向所有客户端推送
});
clients.length = 0; // 清空客户端列表
}
性能优化建议
- 设置合理的超时时间(通常 25-30秒)
- 实现连接断开后的自动重连机制
- 对非活动连接进行心跳检测
- 考虑使用消息队列管理推送事件
- 在浏览器端实现退避策略避免频繁重试
适用场景比较
| 技术 | 协议 | 方向性 | 延迟 | 浏览器支持 |
|---|---|---|---|---|
| 长轮询 | HTTP | 单向 | 中等 | 广泛 |
| SSE | HTTP | 单向 | 低 | 现代浏览器 |
| WebSocket | WS | 双向 | 最低 | 现代浏览器 |
| Forever Frame | HTTP | 单向 | 中等 | 广泛 |
选择实现方式时应考虑项目需求、浏览器兼容性和服务器基础设施。现代应用推荐优先考虑 SSE 或 WebSocket,传统系统可能需要使用长轮询作为降级方案。







