首选 WebSocket 实现实时仪表盘,需监听四事件、封装指数退避重连、URL 传 token、校验 JSON;次选 EventSource(仅服务端推送)或 fetch+setInterval(8~15 秒轮询、暂停后台标签页请求);DOM 更新须解耦渲染与数据接收,高频数据需降采样、canvas 需 clearRect。

别用 <meta http-equiv="refresh"> —— 它强制整页重载,会清空表单、丢失滚动位置、重复提交、破坏登录态,且无法带认证头或做失败重试。
WebSocket 是实时仪表盘的首选方案
它建立浏览器与服务端之间的全双工长连接,数据秒级甚至毫秒级到达,避免轮询开销。关键不是“能不能连”,而是“连上了怎么稳住”:
- 必须监听
open、message、error、close四个事件,缺一不可;close里不加重连逻辑,等于没连 - 生产环境务必封装指数退避重连(如 1s → 2s → 4s → 8s),并限制最大重试次数(例如 5 次),否则服务端重启时前端会雪崩式重连
- 连接成功后立即发认证 token:推荐拼在 URL 里(
new WebSocket('ws://host/path?token=xxx')),比首次send()更可靠,避免 race condition -
message回调中必须用JSON.parse()前校验字符串有效性,捕获SyntaxError,否则一条脏数据就能让整个仪表盘卡死
fetch + setInterval 轮询只适合低频场景
当服务端不支持 WebSocket 或 EventSource 时,轮询是次选,但必须控制节奏和容错:
- 间隔别设 3 秒或 5 秒——8~15 秒更合理,既降低服务端压力,也减少用户感知到的“抖动”
- 每次 fetch 必须加
credentials: 'include',否则 cookie 或 session 无法透传,登录态一刷就丢 - 要在
catch里做降级处理(比如显示“最后更新:2 分钟前”),而不是throw中断后续轮询 - 用户切到其他标签页时,应暂停轮询:
document.hidden为 true 时clearInterval,切回再恢复,否则后台标签页还在疯狂请求
EventSource 适合轻量事件推送
比 WebSocket 更轻量,自动重连、仅支持 GET、天然兼容 CORS,适合状态变更少但要求及时通知的场景(如审批通过、告警触发):
立即学习“前端免费学习笔记(深入)”;
- 服务端响应头必须包含
Content-Type: text/event-stream和Cache-Control: no-cache,否则 Chrome 可能缓存并中断流 - 前端用
eventSource.onmessage接收通用消息,用eventSource.addEventListener('order_updated', ...)接收指定类型事件,避免 if-else 判断 type 字段 - 不支持发送数据到服务端,所以不能用来“上报操作日志”或“确认已读”,这类需求得换 WebSocket
- 某些老旧内网环境(如 IE11 或部分国产浏览器)不支持,上线前必须实测
DOM 更新必须解耦渲染与数据接收
无论用哪种数据源,UI 卡顿往往不是因为网络慢,而是因为每条消息都直接触发重绘:
- 数值类指标(如 CPU 百分比)用
element.innerText = value.toFixed(1)即可,别套innerHTML或反复创建 DOM 节点 - 图表类组件(如折线图)优先调用
.update()方法(Chart.js/ECharts 均支持),而非.destroy() + .render()全量重建 - 高频数据(>20Hz)进 UI 前必须降采样或节流:用
requestAnimationFrame批量合并,控制最终渲染帧率 ≤ 30fps - 所有动态 canvas 绘制必须在
ctx.clearRect()后执行,否则旧指针、旧曲线残留,视觉上像“鬼影”
真正难的从来不是“怎么拿到新数据”,而是“拿到后怎么不崩、不卡、不丢、不闪”。WebSocket 连不上时有没有 fallback?轮询失败三次后要不要弹提示?canvas 渲染掉帧了用户是否感知异常?这些细节堆起来,才是仪表盘能否真正在大屏上挂 7×24 小时的关键。



















