轮询机制实现
前端轮询的实现方式、与长轮询的区别及替代方案
问题
什么是轮询?如何在前端实现轮询?
解答
什么是轮询
轮询是指在固定的时间间隔内,定时向服务器发送请求,获取最新数据的过程。即使服务器没有数据更新,客户端也会持续发送请求。
轮询 vs 长轮询
轮询:固定时间间隔发送请求,服务器立即响应(无论是否有新数据)。
长轮询:客户端发送请求后,服务器如果没有新数据,会将请求挂起,直到有数据更新或超时才返回。
前端实现方式
基于 setInterval 的轮询
function polling() {
setInterval(() => {
fetch('/api/data')
.then(res => res.json())
.then(data => {
console.log('获取数据:', data);
})
.catch(err => console.error(err));
}, 3000); // 每 3 秒请求一次
}
基于 setTimeout 的递归轮询
function polling() {
fetch('/api/data')
.then(res => res.json())
.then(data => {
console.log('获取数据:', data);
setTimeout(polling, 3000); // 请求完成后再等待 3 秒
})
.catch(err => {
console.error(err);
setTimeout(polling, 3000);
});
}
轮询的缺点
- 产生大量无效请求,浪费带宽和服务器资源
- 对服务器压力大
- 频繁请求可能被视为恶意行为,导致 IP 被封禁
替代方案
WebSocket
const ws = new WebSocket('ws://example.com/socket');
ws.onmessage = (event) => {
console.log('收到数据:', event.data);
};
Server-Sent Events (SSE)
const eventSource = new EventSource('/api/stream');
eventSource.onmessage = (event) => {
console.log('收到数据:', event.data);
};
关键点
- 轮询会产生大量无效请求,递归轮询(setTimeout)比定时轮询(setInterval)更可控
- 长轮询通过挂起请求减少无效请求,但仍基于 HTTP
- WebSocket 提供双向实时通信,SSE 提供服务器到客户端的单向推送
- 对于实时性要求高的场景,优先使用 WebSocket 或 SSE 替代轮询
目录