gdoo/public/assets/js/gdoo.websocket.js

151 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* `GdooWebSocket` constructor.
*
* @param {Object} opts
* {
* url websocket链接地址
* pingTimeout 未收到消息多少秒之后发送ping请求默认15000毫秒
pongTimeout 发送ping之后未收到消息超时时间默认10000毫秒
reconnectTimeout 尝试重连的间隔时间默认2000毫秒
pingMsg ping 消息值默认ping
repeatLimit 重连尝试次数。默认不限制
* }
* @api public
*/
var GdooWebSocket = function({
url,
pingTimeout = 15000,
pongTimeout = 10000,
reconnectTimeout = 2000,
pingMsg = 'ping',
repeatLimit = null
}){
this.opts = {
url: url,
pingTimeout: pingTimeout,
pongTimeout: pongTimeout,
reconnectTimeout: reconnectTimeout,
pingMsg: pingMsg,
repeatLimit: repeatLimit
};
this.ws = null; //websocket实例
this.repeat = 0;
// override hook function
this.onclose = () => {};
this.onerror = () => {};
this.onopen = () => {};
this.onmessage = () => {};
this.onreconnect = () => {};
this.onsend = () => {};
this.onreconnectCountDown = () => {};
this.createWebSocket();
}
GdooWebSocket.prototype.createWebSocket = function() {
try {
this.ws = new WebSocket(this.opts.url);
this.initEventHandle();
} catch (e) {
this.reconnect();
throw e;
}
};
GdooWebSocket.prototype.initEventHandle = function() {
this.ws.onclose = (e) => {
this.onclose(e);
this.reconnect();
};
this.ws.onerror = (e) => {
this.onerror(e);
this.reconnect();
};
this.ws.onopen = () => {
this.repeat = 0;
this.onopen();
//心跳检测重置
this.heartCheck();
};
this.ws.onmessage = (event) => {
this.onmessage(event);
//如果获取到消息,心跳检测重置
//拿到任何消息都说明当前连接是正常的
this.heartCheck();
};
};
GdooWebSocket.prototype.reconnect = function() {
if (this.opts.repeatLimit > 0 && this.opts.repeatLimit <= this.repeat) return; //limit repeat the number
if (this.lockReconnect || this.forbidReconnect) return;
this.lockReconnect = true;
this.repeat++; //必须在lockReconnect之后避免进行无效计数
this.onreconnect();
// 倒计时重连
this.countDown = options.reconnectTimeout / 1000;
this.reconnectCountDown();
// 没连接上会一直重连,设置延迟避免请求过多
setTimeout(() => {
this.createWebSocket();
this.lockReconnect = false;
}, this.opts.reconnectTimeout);
};
GdooWebSocket.prototype.send = function(msg) {
this.ws.send(msg);
this.onsend(msg);
};
//心跳检测
GdooWebSocket.prototype.heartCheck = function() {
this.heartReset();
this.heartStart();
};
GdooWebSocket.prototype.heartStart = function() {
// 不再重连就不再执行心跳
if (this.forbidReconnect) return;
this.pingTimeoutId = setTimeout(() => {
// 这里发送一个心跳,后端收到后,返回一个心跳消息,
// onmessage拿到返回的心跳就说明连接正常
this.ws.send(this.opts.pingMsg);
this.onsend(this.opts.pingMsg);
// 如果超过一定时间还没重置,说明后端主动断开了
this.pongTimeoutId = setTimeout(() => {
// 如果onclose会执行reconnect我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
this.ws.close();
}, this.opts.pongTimeout);
}, this.opts.pingTimeout);
};
GdooWebSocket.prototype.reconnectCountDown = function() {
this.onreconnectCountDown(this.countDown);
if (this.countDown > 0) {
this.countDownTimeoutId = setTimeout(() => {
this.reconnectCountDown();
}, 1000);
}
this.countDown--;
}
GdooWebSocket.prototype.heartReset = function() {
clearTimeout(this.pingTimeoutId);
clearTimeout(this.pongTimeoutId);
clearTimeout(this.countDownTimeoutId);
};
GdooWebSocket.prototype.close = function() {
// 如果手动关闭连接,不再重连
this.forbidReconnect = true;
this.heartReset();
this.ws.close();
};