import { getByValue } from '@/enum/socketMessage.js'; import { encodeMessage, decodeMessage } from './socketMessage.js'; import { $socket_base_url } from '@/api/index.js'; class FYWebSocket extends WebSocket { constructor() { super($socket_base_url); return this; } /** * heartBeatConfig 心跳连接参数 * time: 心跳时间间隔 * timeout: 心跳超时间隔 * reconnect: 断线重连时间间隔 * reconnectFunc 断线重连函数 * messageManager 消息管理器 */ init(reconnectFunc, messageManager) { this.onopen = this.openHandler; // 连接成功后的回调函数 this.onclose = this.closeHandler; // 连接关闭后的回调 函数 this.onmessage = this.messageHandler; // 收到服务器数据后的回调函数 this.onerror = this.errorHandler; // 连接发生错误的回调方法 this.heartBeatConfig = { time: 30 * 1000, timeout: 2 * 1000, reconnect: 30 * 1000 }; // 心跳连接配置参数 this.isReconnect = typeof reconnectFunc === 'function'; // 记录是否断线重连 this.reconnectFunc = reconnectFunc; // 断线重连函数 this.messageManager = messageManager; // 消息处理管理器 this.reconnectTimer = null; // 记录断线重连的时间器 this.startHeartBeatTimer = null; // 记录心跳时间器 this.webSocketState = false; // 记录socket连接状态 true为已连接 } // 获取消息 getMessage({ data }) { return decodeMessage(data); } // 发送消息 sendMessage(type, data) { return this.send(encodeMessage(type, data)); } // 连接成功后的回调函数 openHandler() { console.log('====onopen websocket连接成功===='); // socket状态设置为连接,做为后面的断线重连的拦截器 this.webSocketState = true; // 判断是否启动心跳机制 if (this.heartBeatConfig && this.heartBeatConfig.time) { this.startHeartBeat(this.heartBeatConfig.time); } } // 收到服务器数据后的回调函数 messageHandler(res) { const webSocketMsg = this.getMessage(res); if (!(webSocketMsg && webSocketMsg != null && webSocketMsg != {})) { return; } const type = webSocketMsg.type; const data = webSocketMsg.data; let typeObj = getByValue(type); if (type == 0) { // 将连接状态更新为在线 this.webSocketState = true; console.log('====onmessage websocket心跳检测====', data); } else { // 发送事件 this.messageManager.emit(typeObj.name, data); console.log(`====onmessage websocket${typeObj.label}====`, data); } } // 连接关闭后的回调 函数 closeHandler() { console.log('====onclose websocket关闭连接===='); // 设置socket状态为断线 this.webSocketState = false; // 在断开连接时 清除心跳时间器和 断开重连时间器 this.startHeartBeatTimer && clearTimeout(this.startHeartBeatTimer); this.reconnectTimer && clearTimeout(this.reconnectTimer); this.reconnectWebSocket(); } errorHandler() { console.log('====onerror websocket连接出错===='); // 设置socket状态为断线 this.webSocketState = false; // 重新连接 this.reconnectWebSocket(); } // 心跳初始化方法 time:心跳间隔 startHeartBeat(time) { this.startHeartBeatTimer = setTimeout(() => { // 客户端每隔一段时间向服务端发送一个心跳消息 this.sendMessage('0', Date.now()); this.waitingServer(); }, time); } //在客户端发送消息之后,延时等待服务器响应,通过webSocketState判断是否连线成功 waitingServer() { this.webSocketState = false; setTimeout(() => { // 连线成功状态下 继续心跳检测 if (this.webSocketState) { this.startHeartBeat(this.heartBeatConfig.time); return; } console.log('websocket 心跳无响应, 已经和服务端断线'); // 重新连接时,记得要先关闭当前连接 try { this.close(); } catch (error) { console.log('websocket 当前连接已经关闭'); } // // 重新连接 // this.reconnectWebSocket() }, this.heartBeatConfig.timeout); } // 重新连接 reconnectWebSocket() { // 判断是否是重新连接状态(即被动状态断线),如果是主动断线的不需要重新连接 if (!this.isReconnect) { return; } // 根据传入的断线重连时间间隔 延时连接 this.reconnectTimer = setTimeout(() => { // 触发重新连接函数 console.log('====onerror websocket尝试重连===='); this.reconnectFunc(); }, this.heartBeatConfig.reconnect); } } export { FYWebSocket };