前端实时通信方案对比:WebSocket vs SSE vs setInterval 轮询

📢 前言

在前端开发中,实时数据获取是常见需求。本文从前端视角对比三种主流方案:WebSocketSSE (Server-Sent Events)setInterval 轮询,帮你做出最佳技术选型。


📊 核心对比表格

特性 WebSocket SSE setInterval 轮询
通信方向 全双工(双向通信) 单工(服务端→客户端) 半双工(客户端主动拉取)
实时性 毫秒级 亚秒级 依赖轮询间隔(最低秒级)
协议类型 独立协议(ws:///wss:// 基于 HTTP 长连接 基于 HTTP 短连接
前端复杂度 高(需管理连接状态) 中(事件监听) 低(定时器 + fetch)
移动端电量消耗 高(频繁唤醒射频模块)
兼容性 IE10+ Edge12+(需 Polyfill) 全兼容

🔍 技术方案详解

1. WebSocket

📌 核心特性

  • 双向实时通信:客户端与服务端可同时发送消息
  • 低延迟:适用于高频交互场景(如在线游戏、聊天室)
  • 二进制支持:可传输 ArrayBuffer、Blob 等二进制数据

💻 前端实现

javascript 复制代码
const ws = new WebSocket('wss://api.example.com');

// 连接成功
ws.onopen = () => {
  console.log('WebSocket connected');
  ws.send('Hello Server!');
};

// 接收消息
ws.onmessage = (event) => {
  console.log('Received:', event.data);
};

// 错误处理
ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};

// 关闭连接
ws.onclose = () => {
  console.log('WebSocket closed');
};

⚠️ 注意事项

  • 需手动实现心跳检测防止断开
  • iOS 后台运行超过 30 秒可能断开连接
  • 浏览器同一域名最多保持 6 个 WebSocket 连接

2. SSE (Server-Sent Events)

📌 核心特性

  • 服务端推送:服务端可主动向客户端推送数据
  • 自动重连:内置断线重连机制(默认 3 秒)
  • 轻量级:基于 HTTP 协议,兼容现有基础设施

💻 前端实现

javascript 复制代码
const sse = new EventSource('/api/sse');

// 监听自定义事件
sse.addEventListener('stock_update', (e) => {
  console.log('Stock price:', JSON.parse(e.data));
});

// 通用消息监听
sse.onmessage = (e) => {
  console.log('Message:', e.data);
};

// 错误处理(会自动重连)
sse.onerror = () => {
  console.error('SSE connection error');
};

⚠️ 注意事项

  • 不支持 IE 浏览器(需使用 eventsource polyfill)
  • 只能传输文本数据(二进制需 Base64 编码)
  • Chrome 同一域名最多 6 个 SSE 连接

3. setInterval 轮询

📌 核心特性

  • 简单易用:无需服务端特殊支持
  • 兼容性极佳:所有浏览器均支持
  • 成本可控:适合低频更新场景

💻 前端实现

javascript 复制代码
let pollTimer;

// 启动轮询
function startPolling() {
  pollTimer = setInterval(async () => {
    try {
      const res = await fetch('/api/data');
      const data = await res.json();
      updateUI(data);
    } catch (err) {
      console.error('Polling error:', err);
    }
  }, 5000); // 5秒间隔
}

// 停止轮询
function stopPolling() {
  clearInterval(pollTimer);
}

// 页面隐藏时暂停轮询
document.addEventListener('visibilitychange', () => {
  if (document.hidden) {
    stopPolling();
  } else {
    startPolling();
  }
});

⚠️ 注意事项

  • 高频轮询会导致性能问题(推荐间隔 ≥30 秒)
  • 移动端电量消耗显著增加
  • 可能产生陈旧数据(需配合 ETag 等机制)

🚀 选型建议

决策流程图

javascript 复制代码
是否需要双向通信?
├── 是 → 选择 WebSocket
└── 否 → 是否需要服务端主动推送?
       ├── 是 → 选择 SSE
       └── 否 → 数据更新频率?
               ├── ≤30秒 → 优先考虑 SSE
               └── >30秒 → setInterval 轮询

场景化推荐

场景 推荐方案 理由
在线聊天/多人游戏 WebSocket 需要双向高频通信
股票行情/实时日志 SSE 服务端主动推送,节省带宽
天气预报/配置更新 setInterval 轮询 低频请求,实现简单

🛠 优化技巧

WebSocket

🔧 ​​心跳包与 Nginx 超时的关系​

​核心原则​

  • ​心跳间隔 < Nginx 超时时间​

    例如:若 Nginx 配置 proxy_read_timeout 60s,则建议心跳间隔设为 ​​50-55秒​​,需满足:

    复制代码
    心跳间隔 + 网络抖动缓冲 < Nginx超时时间
  • 使用二进制协议(如 Protocol Buffers)压缩数据

  • 添加心跳包检测连接状态

javascript 复制代码
// WebSocket 心跳机制
const HEARTBEAT_INTERVAL = 50 * 1000; // 50秒
let heartbeatTimer;

ws.onopen = () => {
  // 开启心跳
  heartbeatTimer = setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: 'heartbeat' }));
    }
  }, HEARTBEAT_INTERVAL);

  // 重置心跳计数器
  ws.onmessage = () => {
    clearTimeout(heartbeatTimer);
    heartbeatTimer = setInterval(...); // 重新计时
  };
};

SSE

  • 利用 lastEventId 实现断点续传
javascript 复制代码
// 从 localStorage 读取最后事件ID
let lastEventId = localStorage.getItem('lastSSEId') || '0';

const sse = new EventSource(`/api/sse?lastId=${lastEventId}`);

sse.addEventListener('message', (e) => {
  // 更新最后事件ID
  lastEventId = e.lastEventId;
  localStorage.setItem('lastSSEId', lastEventId);
  
  // 处理数据
  console.log('收到数据:', e.data);
});

sse.addEventListener('error', () => {
  sse.close();
  setTimeout(() => {
    // 断线重连时自动携带 lastEventId
    new EventSource(`/api/sse?lastId=${lastEventId}`);
  }, 3000);
});

setInterval 轮询

  • 使用智能退避策略
javascript 复制代码
let retryCount = 0;
function smartPoll() {
  fetch('/api/data')
    .then(resetRetry)
    .catch(() => {
      const delay = Math.min(2000 * 2 ** retryCount, 30000);
      setTimeout(smartPoll, delay);
      retryCount++;
    });
}

💡 总结

方案 核心优势 最佳场景
WebSocket 双向实时通信 在线协作、实时游戏
SSE 服务端推送 + 自动重连 监控仪表盘、实时通知
setInterval 轮询 简单易用 + 全兼容 低频数据更新、兼容性要求高场景

最终建议:根据业务需求选择合适方案,对于复杂场景可组合使用(如 WebSocket + SSE)实现最佳效果!

相关推荐
崔庆才丨静觅11 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606112 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了12 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅12 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅12 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅13 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment13 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅13 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊13 小时前
jwt介绍
前端
爱敲代码的小鱼13 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax