websocket每隔5秒给服务端send一次信息

文章介绍了WebSocket的使用,包括在Vue项目中每隔5秒发送信息的定时器设置,监听浏览器窗口关闭以优雅断开连接,以及WebSocket连接错误时的重连机制。在遇到发送错误时,问题在于尝试在非OPEN状态下执行send方法,解决方案是检查readyState。同时,文章展示了监听网络状态变化以适应网络断开或恢复的情况。

websocket轮询每隔5秒给服务端send一次信息,主要功能点如下:

  1. socket 采用了定时器 setInterval() 需要清除定时器否则会报错

  1. 监听了突然关闭浏览器窗口,destroyed里面直接监听 window.removeEventListener("beforeunload", e => this.beforeunloadHandler(e)) 然后调用this.webstock.close()关闭socket的长链接。

  1. WebSocket连接发生错误的时候,连接错误 需要重连this.reConnect(),尝试重新连接,本次重连次数大于6次就不连接了,放弃连接。

先上效果图:

一 、功能点一清除定时器:

clearInterval(this.timer) // 清除定时器

二、功能点二监听了突然关闭浏览器窗口:

  mounted() {
    window.addEventListener("beforeunload", e => this.beforeunloadHandler(e))
    window.addEventListener("unload", e => this.unloadHandler(e))
  },
    beforeunloadHandler() {
          this._beforeUnload_time = new Date().getTime();
      },
      unloadHandler(e) {
          this._gap_time = new Date().getTime() - this._beforeUnload_time;
          // debugger
          // 关闭或刷新窗口都保存数据到后台
          // 判断窗口是关闭还是刷新
          if (this._gap_time <= 5) {
              // 关闭连接
        this.webstock.close()
          } 
      }
  destroyed() {
    this.$destroy()
    clearInterval(this.timer) // 清除定时器
    // 页面销毁时关闭长连接
    // if (this.webstock !== null) {
    //   this.webstock.close()
    // } 
    window.removeEventListener("beforeunload", e => this.beforeunloadHandler(e))
    window.removeEventListener("unload", e => this.unloadHandler(e))
  }

三、功能点三WebSocket连接发生错误的时候,连接错误 需要重连

websocketonerror(e) {
      console.log("WebSocket连接发生错误")
      // 连接断开后修改标识
      this.isConnect = false
      // 连接错误 需要重连
      this.reConnect()
      }
    },

全部代码如下:

<template>
</template>

<script>
export default {
  data() {
    return {
      timer: 5000,
      webstock: '', // webSocket使用
      isConnect: false, // webSocket连接标识 避免重复连接
      reConnectNum: 1, // 断开后重新连接的次数 免得后台挂了,前端一直重连
      _beforeUnload_time: null,
      _gap_time: null
    }
  },
  methods: {
    /*webSocket start*/
    initWebSocket() {
      let userId = this.$store.state.user.userId
      if (userId !== null && userId !== '') {
        // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
        // 本地环境
       // let wsServer =
          // `${
          //   location.protocol === "https" ? "wss" : "ws"
          // }://localhost:9106/接口前缀/websocket/` + userId;
 
        // 线上环境
        let wsServer = 'ws://172.16.0.54:8102/api/webSocket/' + userId
        console.log("wsServer:", wsServer)
        this.webstock = new WebSocket(wsServer)
        this.webstock.onopen = this.websocketonopen
        this.webstock.onerror = this.websocketonerror
        this.webstock.onmessage = this.websocketonmessage
        this.webstock.onclose = this.websocketclose
      }
    },
    websocketonopen() {
      console.log("WebSocket连接成功") 
      // 连接建立后修改标识
      this.isConnect = true
      const timeoutInfoId = '420507657544310784'
      clearInterval(this.timer) // 清除定时器
      const that = this
      setInterval(() => {
        if (window.location.pathname === '/standardTemplate') {
          that.webstock.send(timeoutInfoId)
        }
      }, this.timer)
    },
    websocketonerror(e) {
      console.log("WebSocket连接发生错误")
      // 连接断开后修改标识
      this.isConnect = false
      // 连接错误 需要重连
      // this.reConnect()
      if (window.location.pathname === '/standardTemplate') {
        this.reConnect()
      }
    },
    // 接收后端推送过来的消息
    websocketonmessage(e) {
      console.log("message消息:", e.data)
      // if (e != null) {
      //   let str = JSON.parse(e.data)
      // }
    },
    websocketclose(e) {
      console.log("webSocket连接关闭")
      // 连接断开后修改标识
      this.isConnect = false
      this.webstock = ''
      if (window.location.pathname === '/standardTemplate') {
        this.reConnect()
      }
    },
    // 重新连接
    reConnect() {
      console.log("尝试重新连接,本次重连次数:" + this.reConnectNum)
      if (this.reConnectNum > 6) {
        return false
      }
      // 如果已经连上就不再重试了
      if (this.isConnect) return
      this.initWebSocket()
      this.reConnectNum = this.reConnectNum + 1
    },
    /*webSocket end*/
    beforeunloadHandler() {
          this._beforeUnload_time = new Date().getTime();
      },
      unloadHandler(e) {
          this._gap_time = new Date().getTime() - this._beforeUnload_time;
          // debugger
          // 关闭或刷新窗口都保存数据到后台
          // 判断窗口是关闭还是刷新
          if (this._gap_time <= 5) {
              // 关闭连接
        this.webstock.close()
          } 
      }
  },
  created() {
    this.reConnectNum = 1
    this.initWebSocket()
  },
  mounted() {
    window.addEventListener("beforeunload", e => this.beforeunloadHandler(e))
    window.addEventListener("unload", e => this.unloadHandler(e))
  },
  destroyed() {
    this.$destroy()
    clearInterval(this.timer) // 清除定时器
    // 页面销毁时关闭长连接
    // if (this.webstock !== null) {
    //   this.webstock.close()
    // } 
    window.removeEventListener("beforeunload", e => this.beforeunloadHandler(e))
    window.removeEventListener("unload", e => this.unloadHandler(e))
  }
}
</script>

问题一、

报错信息如下:socketReport.vue?8285:51 Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.

要明白这个问题产生的原因,就需要了解websocket的几个状态。通常在实例化一个websocket对象之后,客户端就会与服务器进行连接。但是连接的状态是不确定的,于是用readyState属性来进行标识。它有四个值,分别对应不同的状态:

CONNECTING:值为0,表示正在连接;
OPEN:值为1,表示连接成功,可以通信了;
CLOSING:值为2,表示连接正在关闭;
CLOSED:值为3,表示连接已经关闭,或者打开连接失败。

这样问题的原因就很明显了,之所以数据不能发送出去,是因为websocket还处在“CONNECTING”状态下,连接还没有成功。

解决办法

只要在函数中添加对状态的判断,在状态为OPEN时,执行send方法即可。方法一代码如下

this.init()
if (this.webstock.readyState===1) {
    this.webstock.send()
}

问题二、vue项目中监听电脑网络的状态,突然断开网络或者关机

写法一、

 data() {
        return {
            network: true, //默认有网
        }
}
mounted() {
        window.addEventListener("online", () => {
            console.log("网络已连接:")
            this.network = true
        })
        // 检测断网
        window.addEventListener("offline", () => {
            console.log("已断网:")
            this.network = false
            if (this.webstock !== null) {
                this.webstock.close()
            }    
        })
}

控制台打印的结果:

断开网络的情况

再次连接网络:

写法二、

data() {
        return {
            onLine: navigator.onLine,
    }
}
    mounted() {
        console.log('this.onLine:', this.onLine)
        window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
        window.addEventListener('unload', e => this.unloadHandler(e))
    }
    beforeDestroy(){
        window.removeEventListener('online', this.updateOnlineStatus);
        window.removeEventListener('offline', this.updateOnlineStatus);
    },
 // 检测断网
        updateOnlineStatus(e) {
            const { type } = e
            // this.onLine = type === 'online'
            if (type === 'online') {
                // 网络已连接
                console.log("网络已连接:")
                this.$emit('fatherMethod')
                if (window.location.pathname === '/newReport' || window.location.pathname === '/c3analysis') {
                    if (!this.unLock){
                        this.reConnect()
                    }
                }
            } else if (type === 'offline') {
                // 已断网
                console.log("已断网:")
                if (this.webstock !== null) {
                    this.webstock.close()
                } 
            }
        },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT博客技术分享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值