轮询机制实现

前端轮询的实现方式、与长轮询的区别及替代方案

问题

什么是轮询?如何在前端实现轮询?

解答

什么是轮询

轮询是指在固定的时间间隔内,定时向服务器发送请求,获取最新数据的过程。即使服务器没有数据更新,客户端也会持续发送请求。

轮询 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 替代轮询