/** * `WebsocketHeartbeat` constructor. * * @param {Object} opts * { * url websocket链接地址 * pingTimeout 未收到消息多少秒之后发送ping请求,默认15000毫秒 pongTimeout 发送ping之后,未收到消息超时时间,默认10000毫秒 reconnectTimeout pingMsg * } * @api public */ function WebsocketHeartbeat({ url, userId, pingTimeout = 15000, pongTimeout = 10000, reconnectTimeout = 2000, pingMsg = 'heartbeat' }){ this.opts ={ url: url, userId:userId, pingTimeout: pingTimeout, pongTimeout: pongTimeout, reconnectTimeout: reconnectTimeout, pingMsg: pingMsg }; this.ws = null;//websocket实例 //override hook function this.onclose = () => {}; this.onerror = () => {}; this.onopen = () => {}; this.onmessage = () => {}; this.onreconnect = () => {}; this.createWebSocket(); } WebsocketHeartbeat.prototype.createWebSocket = function(){ try { this.ws = new WebSocket(this.opts.url); this.initEventHandle(); } catch (e) { this.reconnect(); throw e; } }; WebsocketHeartbeat.prototype.initEventHandle = function(){ this.ws.onclose = () => { this.onclose(); this.reconnect(); }; this.ws.onerror = () => { this.onerror(); this.reconnect(); }; this.ws.onopen = () => { this.onopen(); //心跳检测重置 this.heartCheck(); }; this.ws.onmessage = (event) => { var data=JSON.parse(event.data); console.log("qxj onmessage data:"+JSON.stringify(data)); this.onmessage(event); //如果获取到消息,心跳检测重置 //拿到任何消息都说明当前连接是正常的 this.heartCheck(); }; }; WebsocketHeartbeat.prototype.reconnect = function(){ if(this.lockReconnect || this.forbidReconnect) return; this.lockReconnect = true; this.onreconnect(); //没连接上会一直重连,设置延迟避免请求过多 setTimeout(() => { this.createWebSocket(); this.lockReconnect = false; }, this.opts.reconnectTimeout); }; WebsocketHeartbeat.prototype.send = function(msg){ let msgBean={'cmd':this.opts.pingMsg,'userId':this.opts.userId,'msg':msg}; this.ws.send(JSON.stringify(msgBean)); }; //心跳检测 WebsocketHeartbeat.prototype.heartCheck = function(){ this.heartReset(); this.heartStart(); }; WebsocketHeartbeat.prototype.heartStart = function(){ if(this.forbidReconnect) return;//不再重连就不再执行心跳 this.pingTimeoutId = setTimeout(() => { //这里发送一个心跳,后端收到后,返回一个心跳消息, //onmessage拿到返回的心跳就说明连接正常 this.send(this.opts.pingMsg); //如果超过一定时间还没重置,说明后端主动断开了 this.pongTimeoutId = setTimeout(() => { //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次 this.ws.close(); }, this.opts.pongTimeout); }, this.opts.pingTimeout); }; WebsocketHeartbeat.prototype.heartReset = function(){ clearTimeout(this.pingTimeoutId); clearTimeout(this.pongTimeoutId); }; WebsocketHeartbeat.prototype.close = function(){ //如果手动关闭连接,不再重连 this.forbidReconnect = true; this.heartReset(); this.ws.close(); }; if(window) window.WebsocketHeartbeat = WebsocketHeartbeat; export default WebsocketHeartbeat;