应维护实例级retryCount变量,在onerror和非正常onclose(code≠1000/1001)时递增,达上限(如3次)即停止重连;首次失败即计数,需清空旧定时器并关闭旧实例防泄漏。

WebSocket 连接失败时如何计数并限制重试次数
直接在连接失败回调里维护一个全局或实例级的 retryCount 变量,每次 onerror 或 onclose(且非正常关闭)触发时递增;达到阈值(如 3)后不再调用重连函数。注意:不能只依赖 onerror,因为某些网络中断可能只触发 onclose,且需排除 event.code === 1000(正常关闭)等情形。
实操建议:
-
retryCount必须定义在 WebSocket 实例作用域内(如闭包、类字段),避免多个实例互相干扰 - 重连前先清空已有定时器(
clearTimeout(this.reconnectTimer)),防止多次失败叠加触发多轮重连 - 仅当
event.code !== 1000 && event.code !== 1001时才视为异常关闭,计入重试 - 首次连接失败也应计入 —— 不要等到第二次才开始计数
如何在重连逻辑中判断是否继续尝试
重连函数(如 reconnect())开头就检查当前 retryCount 是否已达到上限。是,则停止;否,则发起新连接,并在新实例上绑定同样的错误/关闭监听逻辑。
示例关键片段:
class SocketClient {
constructor(url) {
this.url = url;
this.retryCount = 0;
this.maxRetries = 3;
this.reconnectTimer = null;
this.connect();
}
<p>connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
this.retryCount = 0; // 成功则重置计数
};
this.ws.onerror = () => {
this.handleConnectionFailure();
};
this.ws.onclose = (event) => {
if (event.code !== 1000 && event.code !== 1001) {
this.handleConnectionFailure();
}
};
}</p><p>handleConnectionFailure() {
this.retryCount++;
if (this.retryCount > this.maxRetries) {
console.warn('WebSocket 重试已达上限,停止连接');
return;
}
clearTimeout(this.reconnectTimer);
this.reconnectTimer = setTimeout(() => this.connect(), 1000 * Math.pow(2, this.retryCount)); // 指数退避
}
}</p>
为什么不能只靠 onerror 判断连接失败
onerror 是事件处理器,但浏览器不保证它一定会被触发 —— 尤其在网络突然断开(如拔网线、切飞行模式)时,往往只触发 onclose,且 event.code 为 0 或未定义。若只监听 onerror,会导致重试逻辑漏判,看似“没失败”实则已失联。
HISUI 前端框架基础开发指南。HISUI 是基于 easyui 二次开发的 jQuery UI 组件库,专为医疗信息系统设计。当涉及 HISUI 组件开发、jQuery easyui 表格/表单/布局/窗口、医疗系统前端页面编写时使用此 skill。 涵盖 40 个组件的官方文档参考,支持声明式与编程式两种初始化方式,提供 $cm/$m 数据访问方法。
所以必须同时处理 onclose,并结合 event.code 和 event.reason 做综合判断:
-
event.code === 0:常见于强制断网,应计入重试 -
event.code >= 4000:自定义错误码,通常表示服务端主动拒绝,可选择不重试 -
!event.code且this.ws.readyState === 0:连接未建立即断开,属于初始化失败,必须重试
重连过程中如何避免重复实例和内存泄漏
每次调用 connect() 都会新建 WebSocket 实例,但旧实例若未手动关闭或解绑事件,可能持续持有引用,尤其在频繁失败重试时容易堆积。
安全做法:
- 在
connect()开头加this.ws?.close()(如有旧实例) - 所有事件监听使用箭头函数或显式
bind(this),避免因this失控导致无法清理 - 在页面卸载或组件销毁时(如 React 的
useEffect cleanup),显式调用this.ws?.close()并清除定时器 - 不要在
onopen中重复绑定事件 —— 每次connect()都是全新实例,事件只需绑定一次
重试逻辑真正难的不是计数,而是准确识别“什么叫失败”——网络层无声中断、服务端静默丢包、TLS 握手卡死,这些都不会抛出 JS 错误,只能靠超时检测 + readyState 轮询补位。单纯靠 onerror 和 onclose 仍不够鲁棒。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










