WebSocket心跳

为什么要实现websocket心跳?

在使用原生websocket的时候,如果设备网络断开,不会触发任何函数,前端程序无法得知当前的连接已经断开,这个时候如果调用 websocket.send()方法,浏览器就会发现消息发不出去,便会立刻或一定短时间后(不同浏览器或浏览器版本可能表现不同)触发onclose函数。

1.页面初始化调用initWebSocket函数,目的是创建一个websocket方法

let isLockReconnect = false //避免重复连接
let wsUrl = 'ws://xxx.xx.xx'
let ws = null
let reconnectTimer = null
let reconnectDelayTime = 10000;//重复连接延迟时间,避免一直重复连接
let heartCheckIntervalTime = 30000;//心跳检测间隔时间
function initWebSocket(){
  try{
    ws = new WebSocket(wsUrl)
    wsMonitor()
  }catch(e){
    console.log(e)
    reconnect(wsUrl)
  }
}

2.实现wsMonitor方法,该方法内把一些监听事件进行封装

function wsMonitor (){
  ws.onclose = ()=>{
    console.log('连接关闭')
    reconnect(wsUrl)
  }
  ws.onerror = ()=>{
    console.log('发生异常')
    reconnect(wsUrl)
  }
  ws.onopen = ()=>{
    console.log('连接打开')
    heartCheck.start()
  }
  ws.onmessage = ()=>{
    console.log('接收到消息')
    heartCheck.start()
  }
}

当网络断开,onerror,onclose事件可以监听到,会调用reconnect方法进行重连操作,正常情况下联通成功onopen方法会监听到,接收到数据时会被onmessage事件监听到

3.重连操作reconnect方法实现

function reconnect(wsUrl){
  if(isLockReconnect){
    return
  }
  isLockReconnect = true;
  reconnectTimer && clearTimeout(reconnectTimer)
  reconnectTimer = setTimeout(()=>{
    initWebSocket(wsUrl)
    isLockReconnect = false
  },reconnectDelayTime)//设置延迟连接
}

4.实现心跳监测代码(个人理解:关键点在heartCheck.start方法;)

  • onopen、onmessage都执行heartCheck.start方法
  • 间隔heartCheckIntervalTime时间询问是否断联
  • 若未断联,onmessage再次执行heartCheck.start方法,则清除定时器
  • 若断联,执行ws.close方法(内部逻辑进行重连)
let heartCheck = {
    timeoutObj:null,
    serverTimeoutObj:null,
    start(){
        this.timeoutObj && clearTimeout(this.timeoutObj)
        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj)
        this.timeoutObj = setTimeout(()=>{
            ws.send('Is Server Alive?')
            this.timeoutObj = null
            this.serverTimeoutObj = setTimeout(()=>{
                ws.close()
                this.serverTimeoutObj = null
            },heartCheckIntervalTime)
        },heartCheckIntervalTime)
    }
}

构造函数版

class WebSocketHeart{
    constructor(wsUrl){
        this.isLockConnect = false //是否锁死重复连接
        this.wsUrl = wsUrl //websocketURL地址
        this.ws = null //websocket实例对象
        this.reconnectTimer = null //重连定时器
        this.reconnectDelayTime = 10000 //重连延迟时间
        this.heartCheckInterValTime = 30000 //心跳检测间隔时间
        this.timeoutObj = null //心跳检测定时器
        this.serverTimeoutObj = null //心跳检测服务端定时器
    }
    initWebSocket(){
        try{
            this.ws = new WebSocket(this.wsUrl)
            this.wsMonitor()
        }catch(err){
            console.log(err)
            this.reconnect()
        }
    }
    wsMonitor(){
        this.ws.onclose = () => {
            console.log('连接关闭')
            this.reconnect(this.wsUrl)
        }
        this.ws.onerror = () => {
            console.log('连接错误')
            this.reconnect(this.wsUrl)
        }
        this.ws.onopen = () => {
            console.log('连接打开')
            this.heartCheck()
        }
        this.ws.onmessage = () => {
            console.log('接收消息')
            this.heartCheck()
        }
    }
    reconnect(wsUrl){
        if(!this.isLockConnect){
            return
        }
        this.isLockConnect = true
        this.reconnectTimer && clearTimeout(this.reconnectTimer)
        this.reconnectTimer = setTimeout(()=>{
            this.initWebSocket(wsUrl)
            this.isLockConnect = false
        },this.reconnectDelayTime)
    }
    heartCheck(){
        this.timeoutObj && clearTimeout(this.timeoutObj)
        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj)
        this.timeoutObj = setTimeout(() => {
            this.ws.send('Is Server Alive ?')
            this.timeoutObj = null
            this.serverTimeoutObj = setTimeout(() => {
                this.ws.close()
                this.serverTimeoutObj = null
            },this.heartCheckInterValTime)
        },this.heartCheckInterValTime)
    }
}
posted @ 2020-05-26 13:19  671_MrSix  阅读(249)  评论(0)    收藏  举报