Vue中使用WebSocket进行双向数据传输

716 阅读2分钟

WebSocket的简介

WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

websocket的使用

创建websockt实例

   methods:{
        //初始化websocket
        initWebsocket(){
            try{
                this.wsUrl = 'websocket地址'
            if('Websocket' in window){
                //创建websocket实例,并绑定地址
                this.socket = new Websocket(this.wsUrl)
            }else{
                console.log('您的浏览器不支持websocket')
            }
            //websocket连接成功,执行websocketonopen函数
            this.socket.onopen = this.websocketonopen
            //websocket连接失败,执行websocketonerror函数
            this.socket.onerror = this.websocketonerror
            //websocket连接成功后,后端返回数据执行websocketonmessage函数
            this.socket.onmessage = this.websocketonmessage
            //websocket关闭,执行websocketclose函数
            this.socket.onclose = this.websocketonclose
            }catch(err){
                console.log(err)
                //连接失败重新连接
                this.reconnect()
            },
            
            //连接成功执行函数
            websocketonopen(){
                console.log('Webcocket连接成功')
            }
            //连接失败执行函数
            websocketonerror(e){
                console.log('Websocket连接发生错误',e)
            }
        }
    }

场景阐述

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

后端websocket服务也可能出现异常,连接断开后前端也并没有收到通知,因此需要前端定时发送心跳消息ping,后端收到ping类型的消息,立马返回pong消息,告知前端连接正常。如果一定时间没收到pong消息,就说明连接不正常,前端便会执行重连。

为了解决以上两个问题,以前端作为主动方,定时发送ping消息,用于检测网络和前后端连接问题。一旦发现异常,前端持续执行重连逻辑,直到重连成功。

解决问题:
有心跳检测及自动重连机制,当网络断开或者后端服务问题造成客户端 websocket 断开,程序会自动尝试重新连接直到再次连接成功

  • 心跳监测的代码
    data(){
        return {
            lockReconnect: false, // 连接失败不进行重连
            maxReconnect: 5, // 最大重连次数,若连接失败
            timeout: 60 * 1000,
        }
    },
    methods:{
        //清空定时器
        reset(){
            this.timer && clearTimeout(this.timer)
            this.servertimer && clearTimeout(this.servertimer)
        },
        //心跳监测
        start(ws){
            this.reset()
            this.time = setTimeout(() =>{
                //发送心跳给后端,如果onmessage拿到返回的心跳就说明连接正常
                ws.send(JSON.stringfy({heart:1}))
                //只有在send不了数据的时候,才会触发下面的定时器,否则不会执行
                this.serverTimer = setTimeout(() =>{
                    //心跳监测没有响应时重新连接
                    this.reconnect()
                })
            },this.timeout)
        },
        //重新连接
        reconnect(){
           console.log('尝试重新连接')
           if(this.lockReconnect || this.maxReconnect <= 0){
               return
           }
           setTimeout(() =>{
               this.maxReconnect--
               this.initWebsocket()
           },this.timeout)
        }
    },
    //组件销毁时关闭websocket
    destroyed(){
        //关闭websocket
        this.sorcket.close()
        this.reset()
    }