export default class WS {constructor(listener) {this.keepAlive = 8000; // 心跳检测保活时间this.dogFood = 0; // 心跳检测标志位this.watchDog = -1; // 心跳检测定时器this.timeout = -1; // 连接超时定时器this.ws = null;this.url = null;this.listener = listener;this.onWebSocketOpen = this.onWebSocketOpen.bind(this);this.onWebSocketError = this.onWebSocketError.bind(this);this.onWebSocketClose = this.onWebSocketClose.bind(this);this.onWebSocketMessage = this.onWebSocketMessage.bind(this);}/*** 连接 WebSocket 服务器* @param {String} url 连接地址* @param {Number} timeout 超时时间*/connect(url, timeout = 3000) {this.disconnect();this.url = url;this.ws = new WebSocket(url);this.ws.addEventListener("open", this.onWebSocketOpen);this.ws.addEventListener("error", this.onWebSocketError);this.ws.addEventListener("close", this.onWebSocketClose);this.ws.addEventListener("message", this.onWebSocketMessage);this.timeout = setTimeout(() => {this.disconnect();this.onWebSocketTimeout();}, timeout);}/*** 断开 WebSocket 连接(设计原因,客户端主动关闭连接不派发 websocket:close 事件)* @param {Number} code 关闭代码(默认 1000 正常关闭)*/disconnect(code = 1000) {clearTimeout(this.timeout);clearInterval(this.watchDog);if (this.ws) {this.ws.removeEventListener("open", this.onWebSocketOpen);this.ws.removeEventListener("error", this.onWebSocketError);this.ws.removeEventListener("close", this.onWebSocketClose);this.ws.removeEventListener("message", this.onWebSocketMessage);this.ws.close(code);}}/*** 发送消息* @param {*} message 消息对象*/send(message) {if (this.ws?.readyState === WebSocket.OPEN) {this.ws.send(JSON.stringify(message));}}// 启动看门狗(心跳检测)startWatchDog() {this.send({ type: "ping" });this.watchDog = setInterval(() => {if (this.dogFood === 0) {clearInterval(this.watchDog);return this.onWebSocketTimeout();}this.dogFood = 0;this.send({ type: "ping" });}, this.keepAlive);}onWebSocketOpen(event) {console.log("WebSocket 连接成功!");clearTimeout(this.timeout);clearInterval(this.watchDog);this.startWatchDog(); // 开始心跳检测if (this.listener?.onOpen) {this.listener.onOpen(event);}}onWebSocketError(event) {console.log("WebSocket 发生错误", event);clearTimeout(this.timeout);clearInterval(this.watchDog);if (this.listener?.onError) {this.listener.onError(event);}}onWebSocketClose(event) {console.log("WebSocket 连接关闭", event);clearTimeout(this.timeout);clearInterval(this.watchDog);if (this.listener?.onClose) {this.listener.onClose(event);}}onWebSocketMessage(event) {this.dogFood = 1;if (this.listener?.onMessage) {this.listener.onMessage(JSON.parse(event.data));}}onWebSocketTimeout() {console.log("WebSocket 连接超时");if (this.listener?.onTimeout) {this.listener.onTimeout(this.ws);}}
}