Vue + websocket implements message notification reception

The WebSocket protocol was born in 2008 and became an international standard in 2011. All browsers already support it.
Its biggest feature is that the server can actively push information to the client, and the client can also actively send information to the server. It is a real two-way equal dialogue and belongs to a kind of server push technology.
 

features

  • Based on the TCP protocol, the implementation of the server is relatively easy;
  • It has good compatibility with HTTP protocol. The default ports are also 80 and 443, and the handshake phase uses the HTTP protocol, so it is not easy to shield during the handshake, and can pass through various HTTP proxy servers;
  • The data format is relatively light, the performance overhead is small, and the communication is efficient;
  • Can send text or binary data
  • There is no same-origin restriction, the client can communicate with any server
  • The protocol identifier is WS (or WSS if encrypted), and the server URL is the URL

1.  Create websocket.js under the utils of the project

// 引入store,用于管理socket推送来的消息
import store from '@/store/index'
import { baseUrl } from '@/config/env'; // 引入公共服务器地址
// 封装websocket对象
const WS = {
    $ws:null, // webscoket实例
    timeout: 8000, // 心跳重连时间,8秒检测一次
    timeoutObj: null, // 定时器
    lockReconnect: false, // 避免重复重连
    reconnectTimes: 0, // 重连次数

    // 初始化webSocket
    createWS: function(data){
        if('WebSocket' in window){
            // eslint-disable-next-line no-undef
            let apiUrl = baseUrl.slice(5,-1) // 字符串切割,切出合适的ip 进行请求
            // let url = 'ws://xxxxx.com:80/xxx', // websocket链接地址
            let url = "ws://" + apiUrl +":10001/ccs-notifier/ws?token=" + data.access_token + '&refurbishToken=' + data.refresh_token;
            this.$ws = new WebSocket(url)
            this.$ws.onopen = this.wsOpen
            this.$ws.onmessage = this.wsMessage
            this.$ws.onerror = this.wsError
            this.$ws.onclose = this.wsClose
        } else {
            alert('Current browser Not support websocket')
        }
    },

    // webSocket 打开
    wsOpen() {
        // WS.$ws.send('Hello WebSockets!')
        store.commit('SET_WS_CONNECT', true)
        // console.log('== websocket open ==')
        // <!--开始心跳-->
        WS.wsStartHeart()
    },

    // websocket 接收到服务器消息
    wsMessage: function(msg) {
        // console.log('== websocket message ==', msg)
        let data = JSON.parse(msg.data);
        // 将接收到的消息存到 vuex 中
        store.commit('SET_WS_MSG', data.data.contJson)
        // 每次接收到服务端消息后 重置websocket心跳
        WS.wsRset()
    },

    // websocket 发生错误
    wsError: function(err){
        console.log('== websocket error ==', err)
        // 发生错误重连socket
        if (WS.reconnectTimes < 10) {
            WS.wsReconnect()
        }
    },
    // websocket 向后端发送消息
    webSocketSend(messsage) {
        WS.$ws.send(JSON.stringify(messsage))
    },

    // websocket 关闭连接
    wsClose: function(event){
        console.log('== websocket close ==', event)
        if (WS.$ws && WS.$ws.readyState === 1) {
            WS.$ws.close()
            store.commit('SET_WS_CONNECT', false)
        }
        const token = store.getters.token
        if (token) {
            if (WS.reconnectTimes < 10) { // 设置重连次数为10次
                WS.wsReconnect()
            }
        }
    },

    // socket开始心跳
    wsStartHeart: function(){
        // WS.timeoutObj && clearTimeout(WS.timeoutObj)
        WS.timeoutObj = setTimeout(function () {
            // 后端要求的参数格式(具体可根据自己的进行修改)
            let params = { 
                contJson:{},
                contactMethodTypeEnum: 'HEARTBEAT_DETECTION', // 心跳检测
            }
            // console.log('心跳中~~~')
            WS.$ws.send(JSON.stringify(params))
        }, WS.timeout)
    },

    // socket 重置心跳
    wsRset: function (){
        clearTimeout(WS.timeoutObj)
        WS.wsStartHeart()
    },

    // socket 重连
    wsReconnect: function (){
        console.log('Reconnection Socket')
        // eslint-disable-next-line no-undef
        if (WS.lockReconnect) return
        WS.reconnectTimes++
        WS.lockReconnect = true
        const userInfo = JSON.parse(window.localStorage.getItem('justech-userInfo'));
        // console.log(userInfo, 'userInfo')
        setTimeout(function () { // 没连接上会一直重连,设置延迟避免请求过多
            WS.createWS(userInfo.content)
            WS.lockReconnect = false
        }, 6000)
    }
}

export default WS

2. Introduce WS in main.js and mount it on the Vue prototype

// 添加 websocket
import WS from '@/utils/websocket'
Vue.prototype.$ws = WS;
// 为防止页面刷新消息数据丢失,在此添加方法,进行重新请求
try {
  const userInfo = JSON.parse(window.localStorage.getItem('userInfo'));
  if (userInfo) {
    WsConnection.createWS(userInfo.content);
  }
} catch (error) {
  console.log(error);
}

3. Create a global data store in store/index.js

const store= new Vuex.Store({
        modules:{
            
        },
        state:{
            webSocketMsg:'',
            webSocketConnect: false,
        },
        mutations:{
            // 存储socket推送消息
            SET_WS_MSG (state, msg) =>{
                state.webSocketMsg = msg
            },
            // 设置socket链接状态
            SET_WS_CONNECT (state, msg) {
                state.webSocketConnect = msg
            }
        },
        getters:{
            
        }
})

4. Use within a single component

computed:{
   getWsMsg (){
      return this.$store.state.webSocketMsg
   }
},
watch:{
   getWsMsg:{
      handler: function(newVal) {
         console.log(newVal)
         alert('接收到webSocket推送'+ newVal)
      }
   }
}

After the login is successful, call the createWS method to establish the websocket

Call wsClose to close  the websocket connection when logging out

So far, the test is valid! ! !

Guess you like

Origin blog.csdn.net/qq_38543537/article/details/130315936