JavaScript中如何对WebSocket接收事件排队实现限速执行?
WebSocket 事件限频队列实现(最高每秒处理1次)
核心思路
基于Promise链式调用实现无依赖任务队列,保证所有WebSocket推送事件按到达顺序串行执行,同时通过时间差校验强制两次处理的最小间隔为1秒,既不会丢失事件,也不会因为事件推送频率过高导致处理逻辑过载。
- 无任何第三方依赖,全部使用原生JS语法实现
- 事件严格按到达顺序执行,不会出现乱序、并发问题
- 自动适配业务逻辑耗时:如果单条事件处理本身耗时超过1秒,下一条会在处理完成后立即执行,无额外等待开销
- 瞬时高流量下的事件自动排队,不会丢失
完整实现代码
// 队列初始值为已完成的Promise,作为链式调用的起点 let taskQueue = Promise.resolve(); // 记录上一次事件处理完成的时间戳 let lastProcessFinishTime = 0; // 配置最小处理间隔,单位毫秒,1000ms即每秒最多处理1次 const MIN_PROCESS_INTERVAL = 1000; const ws = new WebSocket(`wss://hallo.com/ws/`); ws.onmessage = readMessage; /** * 任务入队方法:将新任务追加到队列尾部 * @param {() => Promise<void>} task 异步处理任务 */ function enqueue(task) { taskQueue = taskQueue.then(task); } async function readMessage(event) { // 所有收到的事件统一入队,不直接执行业务逻辑 enqueue(async () => { // 计算需要等待的间隔时间 const currentTime = Date.now(); const needWait = Math.max(0, MIN_PROCESS_INTERVAL - (currentTime - lastProcessFinishTime)); // 等待至满足间隔要求 if (needWait > 0) { await new Promise(resolve => setTimeout(resolve, needWait)); } // 以下替换为实际的事件处理逻辑 print(event) //do important things // 更新最后处理完成时间 lastProcessFinishTime = Date.now(); }) }
原理解释
参考方案的核心就是Promise链式队列逻辑:通过维护一个始终指向队列最后一个任务的Promise变量,每次新任务入队时就把任务挂载到当前Promise的then回调上,再把这个新返回的Promise更新为队列的尾部节点,天然就能保证所有入队任务按顺序串行执行,不需要手动实现数组队列的轮询逻辑。
在此基础上增加时间间隔校验:每个任务执行前先计算和上一次任务完成的时间差,如果间隔不足1秒就等待补足,即可严格实现最高1次/秒的处理频率限制。
内容的提问来源于stack exchange,提问作者Norbert
相关产品推荐
相关产品推荐

