封装类和心跳机制

1

  1. class WebSocketClass {
  2. /**
  3. * @description: 初始化实例属性,保存参数
  4. * @param {String} url ws的接口
  5. * @param {Function} msgCallback 服务器信息的回调传数据给函数
  6. * @param {String} name 可选值 用于区分ws,用于debugger
  7. */
  8. constructor(url, msgCallback, name = 'default') {
  9. this.url = url;
  10. this.msgCallback = msgCallback;
  11. this.name = name;
  12. this.ws = null; // websocket对象
  13. this.status = null; // websocket是否关闭
  14. }
  15. /**
  16. * @description: 初始化 连接websocket或重连webSocket时调用
  17. * @param {*} 可选值 要传的数据
  18. */
  19. connect(data) {
  20. // 新建 WebSocket 实例
  21. this.ws = new WebSocket(this.url);
  22. this.ws.onopen = e => {
  23. // 连接ws成功回调
  24. this.status = 'open';
  25. console.log(`${this.name}连接成功`, e)
  26. // this.heartCheck();
  27. if (data !== undefined) {
  28. // 有要传的数据,就发给后端
  29. return this.ws.send(data);
  30. }
  31. }
  32. // 监听服务器端返回的信息
  33. this.ws.onmessage = e => {
  34. // 把数据传给回调函数,并执行回调
  35. // if (e.data === 'pong') {
  36. // this.pingPong = 'pong'; // 服务器端返回pong,修改pingPong的状态
  37. // }
  38. return this.msgCallback(e.data);
  39. }
  40. // ws关闭回调
  41. this.ws.onclose = e => {
  42. this.closeHandle(e); // 判断是否关闭
  43. }
  44. // ws出错回调
  45. this.onerror = e => {
  46. this.closeHandle(e); // 判断是否关闭
  47. }
  48. }
  49. // heartCheck() {
  50. // // 心跳机制的时间可以自己与后端约定
  51. // this.pingPong = 'ping'; // ws的心跳机制状态值
  52. // this.pingInterval = setInterval(() => {
  53. // if (this.ws.readyState === 1) {
  54. // // 检查ws为链接状态 才可发送
  55. // this.ws.send('ping'); // 客户端发送ping
  56. // }
  57. // }, 10000)
  58. // this.pongInterval = setInterval(() => {
  59. // this.pingPong = false;
  60. // if (this.pingPong === 'ping') {
  61. // this.closeHandle('pingPong没有改变为pong'); // 没有返回pong 重启webSocket
  62. // }
  63. // // 重置为ping 若下一次 ping 发送失败 或者pong返回失败(pingPong不会改成pong),
  64. // //将重启
  65. // console.log('返回pong')
  66. // this.pingPong = 'ping'
  67. // }, 20000)
  68. // }
  69. // 发送信息给服务器
  70. sendHandle(data) {
  71. console.log(`${this.name}发送消息给服务器:`, data)
  72. return this.ws.send(data);
  73. }
  74. closeHandle(e = 'err') {
  75. // 因为webSocket并不稳定,规定只能手动关闭(调closeMyself方法),否则就重连
  76. if (this.status !== 'close') {
  77. console.log(`${this.name}断开,重连websocket`, e)
  78. // if (this.pingInterval !== undefined && this.pongInterval !== undefined) {
  79. // // 清除定时器
  80. // clearInterval(this.pingInterval);
  81. // clearInterval(this.pongInterval);
  82. // }
  83. this.connect(); // 重连
  84. } else {
  85. console.log(`${this.name}websocket手动关闭`)
  86. }
  87. }
  88. // 手动关闭WebSocket
  89. closeMyself() {
  90. console.log(`关闭${this.name}`)
  91. this.status = 'close';
  92. return this.ws.close();
  93. }
  94. }
  95. function someFn(data) {
  96. console.log('接收服务器消息的回调:', data);
  97. }
  98. // const wsValue = new WebSocketClass('ws://121.40.165.18:8800', someFn, 'wsName');
  99. // 这个链接一天只能发送消息50次
  100. const wsValue = new WebSocketClass('wss://echo.websocket.org', someFn, 'wsName');
  101. // 阮一峰老师教程链接
  102. wsValue.connect('立即与服务器通信'); // 连接服务器
  103. // setTimeout(() => {
  104. // wsValue.sendHandle('传消息给服务器')
  105. // }, 1000);
  106. // setTimeout(() => {
  107. // wsValue.closeMyself(); // 关闭ws
  108. // }, 10000)

参考:https://segmentfault.com/a/1190000016797885?utm_source=sf-similar-article

2

  1. var lockReconnect = false; //避免ws重复连接
  2. var ws = null; // 判断当前浏览器是否支持WebSocket
  3. var wsUrl = serverConfig.socketUrl;
  4. createWebSocket(wsUrl); //连接ws
  5. function createWebSocket(url) {
  6. try{
  7. if('WebSocket' in window){
  8. ws = new WebSocket(url);
  9. }
  10. initEventHandle();
  11. }catch(e){
  12. reconnect(url);
  13. console.log(e);
  14. }
  15. }
  16. function initEventHandle() {
  17. ws.onclose = function () {
  18. reconnect(wsUrl);
  19. console.log("llws连接关闭!"+new Date().toLocaleString());
  20. };
  21. ws.onerror = function () {
  22. reconnect(wsUrl);
  23. console.log("llws连接错误!");
  24. };
  25. ws.onopen = function () {
  26. heartCheck.reset().start(); //心跳检测重置
  27. console.log("llws连接成功!"+new Date().toLocaleString());
  28. };
  29. ws.onmessage = function (event) { //如果获取到消息,心跳检测重置
  30. heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的
  31. console.log("llws收到消息啦:" +event.data);
  32. if(event.data!='pong'){
  33. let data = JSON.parse(event.data);
  34. }
  35. };
  36. }
  37. // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
  38. window.onbeforeunload = function() {
  39. ws.close();
  40. }
  41. function reconnect(url) {
  42. if(lockReconnect) return;
  43. lockReconnect = true;
  44. setTimeout(function () { //没连接上会一直重连,设置延迟避免请求过多
  45. createWebSocket(url);
  46. lockReconnect = false;
  47. }, 2000);
  48. }
  49. //心跳检测
  50. var heartCheck = {
  51. timeout: 1000, //1分钟发一次心跳
  52. timeoutObj: null,
  53. serverTimeoutObj: null,
  54. reset: function(){
  55. clearTimeout(this.timeoutObj);
  56. clearTimeout(this.serverTimeoutObj);
  57. return this;
  58. },
  59. start: function(){
  60. var self = this;
  61. this.timeoutObj = setTimeout(function(){
  62. //这里发送一个心跳,后端收到后,返回一个心跳消息,
  63. //onmessage拿到返回的心跳就说明连接正常
  64. ws.send("ping");
  65. console.log("ping!")
  66. self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
  67. ws.close(); //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
  68. }, self.timeout)
  69. }, this.timeout)
  70. }
  71. }
  72. // 收到客户端消息后调用的方法
  73. @OnMessage
  74. public void onMessage(String message, Session session) {
  75. if(message.equals("ping")){
  76. }else{
  77. 。。。。
  78. }
  79. }