WebsocketHeartbeat.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /**
  2. * `WebsocketHeartbeat` constructor.
  3. *
  4. * @param {Object} opts
  5. * {
  6. * url websocket链接地址
  7. * pingTimeout 未收到消息多少秒之后发送ping请求,默认15000毫秒
  8. pongTimeout 发送ping之后,未收到消息超时时间,默认10000毫秒
  9. reconnectTimeout
  10. pingMsg
  11. * }
  12. * @api public
  13. */
  14. function WebsocketHeartbeat({
  15. url,
  16. pingTimeout = 15000,
  17. pongTimeout = 10000,
  18. reconnectTimeout = 2000,
  19. pingMsg = 'heartbeat'
  20. }){
  21. this.opts ={
  22. url: url,
  23. pingTimeout: pingTimeout,
  24. pongTimeout: pongTimeout,
  25. reconnectTimeout: reconnectTimeout,
  26. pingMsg: pingMsg
  27. };
  28. this.ws = null;//websocket实例
  29. //override hook function
  30. this.onclose = () => {};
  31. this.onerror = () => {};
  32. this.onopen = () => {};
  33. this.onmessage = () => {};
  34. this.onreconnect = () => {};
  35. this.createWebSocket();
  36. }
  37. WebsocketHeartbeat.prototype.createWebSocket = function(){
  38. try {
  39. this.ws = new WebSocket(this.opts.url);
  40. this.initEventHandle();
  41. } catch (e) {
  42. this.reconnect();
  43. throw e;
  44. }
  45. };
  46. WebsocketHeartbeat.prototype.initEventHandle = function(){
  47. this.ws.onclose = () => {
  48. this.onclose();
  49. this.reconnect();
  50. };
  51. this.ws.onerror = () => {
  52. this.onerror();
  53. this.reconnect();
  54. };
  55. this.ws.onopen = () => {
  56. this.onopen();
  57. //心跳检测重置
  58. this.heartCheck();
  59. };
  60. this.ws.onmessage = (event) => {
  61. // var data=JSON.parse(event.data);
  62. // console.log("qxj onmessage data:"+JSON.stringify(data));
  63. this.onmessage(event);
  64. //如果获取到消息,心跳检测重置
  65. //拿到任何消息都说明当前连接是正常的
  66. this.heartCheck();
  67. };
  68. };
  69. WebsocketHeartbeat.prototype.reconnect = function(){
  70. if(this.lockReconnect || this.forbidReconnect) return;
  71. this.lockReconnect = true;
  72. this.onreconnect();
  73. //没连接上会一直重连,设置延迟避免请求过多
  74. setTimeout(() => {
  75. this.createWebSocket();
  76. this.lockReconnect = false;
  77. }, this.opts.reconnectTimeout);
  78. };
  79. WebsocketHeartbeat.prototype.send = function(msg){
  80. let msgBean={'cmd':this.opts.pingMsg,'msg':msg};
  81. this.ws.send(JSON.stringify(msgBean));
  82. };
  83. //心跳检测
  84. WebsocketHeartbeat.prototype.heartCheck = function(){
  85. this.heartReset();
  86. this.heartStart();
  87. };
  88. WebsocketHeartbeat.prototype.heartStart = function(){
  89. if(this.forbidReconnect) return;//不再重连就不再执行心跳
  90. this.pingTimeoutId = setTimeout(() => {
  91. //这里发送一个心跳,后端收到后,返回一个心跳消息,
  92. //onmessage拿到返回的心跳就说明连接正常
  93. this.send(this.opts.pingMsg);
  94. //如果超过一定时间还没重置,说明后端主动断开了
  95. this.pongTimeoutId = setTimeout(() => {
  96. //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
  97. this.ws.close();
  98. }, this.opts.pongTimeout);
  99. }, this.opts.pingTimeout);
  100. };
  101. WebsocketHeartbeat.prototype.heartReset = function(){
  102. clearTimeout(this.pingTimeoutId);
  103. clearTimeout(this.pongTimeoutId);
  104. };
  105. WebsocketHeartbeat.prototype.close = function(){
  106. //如果手动关闭连接,不再重连
  107. this.forbidReconnect = true;
  108. this.heartReset();
  109. this.ws.close();
  110. };
  111. if(window) window.WebsocketHeartbeat = WebsocketHeartbeat;
  112. export default WebsocketHeartbeat;