低延迟通信不取决于API选择,而在于全链路对齐:WebSocket是唯一可控起点,需binaryType设为arraybuffer、服务端帧级透传、客户端校验readyState;fetch适合非实时路径;EventSource天生有0.5–3秒延迟,仅适用于监控场景。

达不到硬件要求的通信延迟,不是函数选得不对,是整个链路没对齐——WebSocket、fetch、EventSource 本身没有“低延迟”属性,延迟由你如何用、在哪用、和什么配决定。
WebSocket 不等于低延迟,但它是唯一可控的起点
浏览器里能绕过 HTTP 队头阻塞、维持长连接、发送二进制帧的只有 WebSocket。但它默认不保证低延迟:开连接耗时、TCP慢启动、服务端排队、JS主线程调度抖动都会吃掉毫秒级时间。
- 必须设
socket.binaryType = 'arraybuffer',禁用字符串解析开销 - 服务端不能做 JSON 解包或日志写入再转发,要帧级透传(收到即发,不缓存)
- 客户端发帧前检查
socket.readyState === WebSocket.OPEN,避免队列堆积;失败时不重试,直接标记丢帧 - 在
requestAnimationFrame或setTimeout(..., 0)外围加performance.now()时间戳,剔除 JS 调度误差
fetch + keepalive 适合单次保底,不适合实时交互
fetch 是 HTTP/2+ 的,理论上比老式 AJAX 快,但它每次都要走完整请求-响应周期,DNS、TLS、首字节时间(TTFB)不可控。即使加了 keepalive: true,也只延长连接复用窗口,不解决首包延迟。
- 仅用于初始化配置、心跳上报、错误回传等非实时路径
- 若硬要压延迟,必须配合
cache: 'no-store'和priority: 'high'(Chrome 120+),否则可能被浏览器降级调度 - 禁止在
setInterval里轮询 —— 网络抖动会导致间隔崩坏,实际延迟远超设定值
EventSource 在弱网下更稳,但天生有 0.5–3 秒延迟
EventSource 基于 HTTP 流,靠服务端持续保持连接并推送数据。它自动重连、天然支持文本事件格式,但规范强制要求最小重连间隔为 3 秒(可设 retry: 字段覆盖),且首次建立连接后至少等待第一个 data: 帧才会触发 message 事件。
立即学习“前端免费学习笔记(深入)”;
- 只适用于监控类场景(如日志流、状态广播),不能用于指令下发或双向反馈
- 服务端必须用
text/event-stream+flush()强制输出,否则数据会滞留在缓冲区 - 移动端 Safari 对
EventSource的连接复用支持差,频繁断连会放大延迟
硬件响应时间要求怎么反推函数选择
别从“我想用什么”出发,先看硬件给你的硬约束:
- 目标设备是工业 HMI 或车载屏?端到端要求 ≤ 50ms → 只能走
WebSocket+ Web Worker +AudioContext级别调度,且服务端必须部署在同一局域网 - 智能电视遥控操作反馈要 ≤ 150ms?
WebSocket是底线,但需禁用所有 UI 动画、关闭 CSS transition、用requestAnimationFrame同步渲染 - 只是网页表单提交后快速提示“已保存”?
fetch完全够用,加个AbortSignal.timeout(800)防卡死就行
最容易被忽略的是:延迟不是函数决定的,是你是否让函数运行在不受干扰的上下文里——比如在低电量模式下,WebSocket 的 onmessage 可能被系统节流到每秒只触发一次;又比如在内存紧张的 Chromebook 上,fetch 的 pending 请求会被内核主动丢弃。这些都不是换函数能解决的,得结合 navigator.getBattery()、performance.memory、navigator.hardwareConcurrency 主动降级策略。



















