节流应作用于发送调度层而非单个ws.send(),推荐按连接维度节流或统一通道聚合发送:前者用Map缓存各连接节流函数,后者将请求入队后定时批量发送。

多路 WebSocket 发送(如多个连接并行推送消息)本身不直接适用节流,因为节流是针对“高频回调执行”的控制手段,而发送动作(ws.send())通常由业务逻辑主动触发,不是事件驱动的连续回调。真正需要节流的,是「同一连接内高频调用 send」或「多连接共用一个发送通道」时的输出节奏。
节流应作用于发送调度层,而非单个 ws.send()
WebSocket 实例的 send 方法本身是同步非阻塞的,但高频调用会带来实际问题:
- 底层 TCP 缓冲区积压,触发背压甚至断连
- 服务端限流策略拒绝后续消息(如每秒 20 条上限)
- 多个连接同时发相同类型消息(如心跳、状态上报),造成网络毛刺
这时应在业务层统一收口发送逻辑,用节流约束「调用 send 的频率」,而不是给每个 ws.send 套一层节流函数。
推荐:用节流包装统一发送函数
假设你有 3 个 WebSocket 连接(wsA、wsB、wsC),都需周期性上报设备状态:
立即学习“Java免费学习笔记(深入)”;
- 不要这样写(无效且混乱):
throttle(() => wsA.send(msg), 1000)(); throttle(() => wsB.send(msg), 1000)(); ... - 应该这样设计:
定义一个受控的dispatchMessage(target, data),内部按目标连接做节流分组;或更优——把所有上报请求先入队,再用节流驱动批量发送
按连接维度节流(适合差异化节奏)
若各连接语义不同(如 A 传日志、B 传指令、C 传心跳),可为每条连接单独节流:
- 用 Map 缓存每个
ws对应的节流函数:const sendThrottled = new Map();<br>function getThrottledSend(ws, interval = 500) {<br> if (!sendThrottled.has(ws)) {<br> sendThrottled.set(ws, throttle((data) => ws.send(data), interval));<br> }<br> return sendThrottled.get(ws);<br>} - 调用时:
getThrottledSend(wsA, 300)({ type: 'log', msg });<br>getThrottledSend(wsB, 1000)({ type: 'cmd', op: 'reboot' });
统一通道 + 时间窗口聚合(适合高吞吐同构消息)
当多路发送内容结构一致(如全是传感器采样点),更高效的做法是合并调度:
- 所有发送请求先推入一个共享队列:
const sendQueue = [];<br>function queueSend(ws, data) { sendQueue.push({ ws, data }); } - 用节流函数定期清空队列(例如每 60ms 最多发 10 条):
const flushSender = throttle(() => {<br> const batch = sendQueue.splice(0, 10);<br> batch.forEach(({ ws, data }) => {<br> if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify(data));<br> });<br>}, 60);
这种方式天然避免重复节流开销,也便于加失败重试、序列号、压缩等增强逻辑。


















