WebsocketHeartbeat.js 4.0 KB

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