闭包节流需深度耦合连接状态以防止雪崩并保持恢复灵敏度:封装失败次数、退避延迟、时间戳和重试标志,采用时间戳版节流逻辑,协同心跳状态机实现自愈式控速,并避免引用泄漏。

在网络长连接(如 WebSocket、SSE 或自定义 TCP 心跳通道)中,断线自动重连若不做节流控制,极易在抖动期间爆发大量重试请求,压垮客户端资源或触发服务端限流。闭包节流不是“加个 delay 就完事”,而是要让重连行为与连接状态深度耦合——既防止雪崩,又不牺牲恢复灵敏度。
用闭包封装重连状态与退避节奏
每次创建重连控制器时,通过闭包私有保存关键变量:失败次数、当前退避延迟、上次尝试时间戳、是否正在重试中。这些变量对外不可见,但可被重试逻辑持续读写,天然避免多实例干扰或全局污染。
- 失败计数:每失败一次递增,用于计算指数退避值(如 delay = Math.min(30000, baseDelay * 2ⁿ))
- lastAttempt:记录上一次调用重试的时间戳,配合节流判断“是否允许立刻再试”
- isRetrying:布尔标志,防止并发触发多个重连任务
- timer(定时器版)或 lastTime(时间戳版):按策略选其一,统一由闭包管理,不混用
选对节流逻辑:时间戳版更适合重连场景
重连不是“等用户松手再执行”,而是“网络一恢复就得尽快连上”。所以首选时间戳版节流:首次断线立即发起重试,后续在退避窗口内拒绝重复触发,窗口结束后才允许下一次尝试。它响应快、无延迟偏差、不依赖定时器清理逻辑,更贴合状态机的确定性要求。
- 每次 detectDisconnect 触发时,读取 Date.now(),对比 lastAttempt + currentDelay
- 满足条件才执行 connect(),并更新 lastAttempt 和 isRetrying
- 成功连接后,重置失败计数和延迟为初始值(如 500ms),退出节流周期
与心跳检测状态机协同,实现“自愈式”控速
节流只是手段,目标是让整个连接生命周期具备自愈能力。闭包把节流逻辑嵌入心跳状态机中,形成闭环:
- 心跳超时 → 触发 disconnect → 进入重连节流判断
- 重连成功 → 上报健康状态 → 清除节流状态、重置退避
- 连续失败达阈值(如 5 次)→ 切换至“保守模式”(最大延迟 + 后台静默探测)
- 收到服务端主动 close 指令 → 立即终止所有节流定时器,不重试
避免闭包引用泄漏,保障长期运行稳定
长连接常驻页面数小时甚至数天,闭包若意外持有大对象(如整个 WebSocket 实例、未清理的事件监听器、大型缓存数据),会阻碍垃圾回收,引发内存缓慢增长。
- 节流闭包中只保留必要状态:数字、布尔、函数引用,不存 event、dom 元素或 this 上下文
- 连接关闭或销毁时,手动 clearTimeout(timer),并将 timer、lastAttempt 等设为 null
- 若使用 RAF 替代 setTimeout(适合视觉反馈类重连提示),闭包仅维护 isQueued 标志,更轻量安全











