vue + websocket 实现消息通知接收

WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
 

特点

  • 建立在TCP协议之上,服务端的实现比较容易;
  • 与HTTP协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用HTTP协议,因此握手时不容易屏蔽,能通过各种HTTP代理服务器;
  • 数据格式比较轻量,性能开销小,通信高效;
  • 可以发送文本,也可以发送二进制数据
  • 没有同源限制,客户端可以与任意服务器通信
  • 协议标识符是 WS(如果加密,则为WSS),服务器网址就是URL

1、在项目的 utils 下创建 websocket.js

// 引入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、在 main.js 中引入 WS,挂载到 Vue 原型上

// 添加 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、在 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、单个组件内使用

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

登录成功之后调用 createWS 方法进行 websocket 的建立

退出登录的时候调用 wsClose 关闭 websocket 连接

至此完成,测试有效!!!

猜你喜欢

转载自blog.csdn.net/qq_38543537/article/details/130315936