vue中使用websocket实现站内信
  0yB7pUbXdkep 2023年11月30日 26 0

1.utils里新建websoket.js

import Vue from 'vue'

import { Message } from 'element-ui'

let v = new Vue()

v.$message = Message;

var webSocket = null;

var isConnect = false; //连接状态

var globalCallback = function(e){ console.log(e) };//定义外部接收数据的回调函数

var reConnectNum = 0;//重连次数

let userId = sessionStorage.getItem("userId")

var websocketUrl =  `ws://192.168.124.60:9098/websocket/${userId}`;

//心跳设置

var heartCheck = {

    heart:"heart",//心跳包

    timeout: 45 * 1000, //每段时间发送一次心跳包 这里设置为60s

    heartbeat: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象)

    start: function () {

        this.heartbeat = setInterval(()=>{

            if (isConnect){

                webSocketSend(this.heart);

            }else{

                this.clear();

            }

        }, this.timeout);

    },

    reset: function () {

        clearInterval(this.heartbeat);

        this.start();

    },

    clear:function(){

        clearInterval(this.heartbeat);

    }

}

//初始化websocket

function initWebSocket(callback) {

    //此callback为在其他地方调用时定义的接收socket数据的函数

    if(callback){

        if(typeof callback == 'function'){

            globalCallback = callback

        }else{

            throw new Error("callback is not a function")

        }

    }

    if ("WebSocket" in window) {

        webSocket = new WebSocket(websocketUrl);//创建socket对象

    } else {

        Message({

            message: '该浏览器不支持websocket!',

            type: 'warning'

        });

        return

    }

    //打开

    webSocket.onopen = function() {

        webSocketOpen();

    };

    //收信

    webSocket.onmessage = function(e) {

        webSocketOnMessage(e);

    };

    //关闭

    webSocket.onclose = function(e) {

        webSocketOnClose(e);

    };

    //连接发生错误的回调方法

    webSocket.onerror = function(e) {

        webSocketonError(e);

    };

}

//连接socket建立时触发

function webSocketOpen() {

    console.log("WebSocket连接成功");

    //首次握手

    webSocketSend(heartCheck.heart);

    isConnect = true;

    heartCheck.start();

    reConnectNum = 0;

}


//客户端接收服务端数据时触发,e为接受的数据对象

function webSocketOnMessage(e) {

    console.log("websocket信息:");

    console.log(e.data)

    if(e.data == "stopUser") {

        Message({

            message: '你已被上级管理员停用即将跳转登录页',

            type: 'warning'

        });

        setTimeout(() => {

            window.location.href = vueConfig.jqUrl + "vue/web/login"

        }, 3000);

    }

    const data = JSON.parse(e.data);//根据自己的需要对接收到的数据进行格式化

    globalCallback(data);//将data传给在外定义的接收数据的函数,至关重要。

}


//socket关闭时触发

function webSocketOnClose(e){

    heartCheck.clear();

    isConnect = false; //断开后修改标识

    console.log(e)

    console.log('webSocket已经关闭 (code:' + e.code + ')')

    //被动断开,重新连接

    if(e.code == 1006){

        if(reConnectNum < 3){

            initWebSocket();

            ++reConnectNum;

        }else{

            v.$message({

                message: 'websocket连接不上,请刷新页面或联系开发人员!',

                type: 'warning'

            });

        }

    }

}


//连接发生错误的回调方法

function webSocketonError(e){

    heartCheck.clear();

    isConnect = false; //断开后修改标识

    console.log("WebSocket连接发生错误:");

    console.log(e);

}



//发送数据

function webSocketSend(data) {

    webSocket.send(JSON.stringify(data));//在这里根据自己的需要转换数据格式

}

//在其他需要socket地方主动关闭socket

function closeWebSocket(e) {

    webSocket.close();

    heartCheck.clear();

    isConnect = false;

    reConnectNum = 0;

}

//在其他需要socket地方接受数据

function getSock(callback) {

    globalCallback = callback

}

//在其他需要socket地方调用的函数,用来发送数据及接受数据

function sendSock(agentData) {

    //下面的判断主要是考虑到socket连接可能中断或者其他的因素,可以重新发送此条消息。

    switch (webSocket.readyState) {

        //CONNECTING:值为0,表示正在连接。

        case webSocket.CONNECTING:

            setTimeout(function() {

                sendSock(agentData, callback);

            }, 1000);

        break;

        //OPEN:值为1,表示连接成功,可以通信了。

        case webSocket.OPEN:

            webSocketSend(agentData);

        break;

        //CLOSING:值为2,表示连接正在关闭。

        case webSocket.CLOSING:

            setTimeout(function() {

                sendSock(agentData, callback);

            }, 1000);

        break;

        //CLOSED:值为3,表示连接已经关闭,或者打开连接失败。

        case webSocket.CLOSED:

        // do something

        break;

        default:

        // this never happens

        break;

    }

}


export default {

  initWebSocket,

  closeWebSocket,

  sendSock,

  getSock

};

2.main.js引入挂载原

import Vue from "vue";

import App from "./App.vue";

import router from "./router";

import store from "./store";

import axios from "./utils/api/index";

import utils from "./utils";

import socketApi from "./utils/websocket";

Vue.prototype.$socketApi = socketApi;//websocket挂在原型上

3.使用

beforeDestroy() {//销毁的生命周期

       this.$socketApi.closeWebSocket();

  },

  mounted() {//挂载的生命周期

    this.$socketApi.initWebSocket(this.getsocketResult);

  },

 methods: {

    // socket信息返回接受函数

       getsocketResult(data) {

         console.log(data);

       },

       //发送socket信息

       websocketSend(data) {

         this.$socketApi.sendSock(data);

       },

 },

4.业务中的使用

export default {

  data() {

    return {

      badgeValue: 0, // 消息总条数

      // websocket消息推送

      ws: null, // websocket实例

      wsUrl: "", // websocket连结url

      tt: null,

      heartCheck: null,

      timeoutObj: null,

      serverTimeoutObj: null,

      timer: null, // 定时器

      lockReconnect: false,

    };

  },

  methods: {

    // 页面获取用户信息

    initPage() {

      const loginInfo = JSON.parse(localStorage.getItem("loginInfo"));

      this.wsUrl = `wss://xxxxxxxxx/api/management/wsmsg/${loginInfo.userId}`;

      window.clearTimeout(this.timeoutObj);

      window.clearTimeout(this.serverTimeoutObj);

      window.clearTimeout(this.tt);

      this.createWebSocket();

    },

    // 创建websocket

    createWebSocket() {

      try {

        this.ws = new WebSocket(this.wsUrl);

        this.initWebScoketFun();

      } catch (e) {

        this.reconnect(this.wsUrl);

      }

    },

    // websocket消息提醒

    initWebScoketFun() {

      const timeout = 30000;

      this.timeoutObj = null;

      this.serverTimeoutObj = null;

      this.heartCheck = {

        start: () => {

          this.timeoutObj && window.clearTimeout(this.timeoutObj);

          this.serverTimeoutObj &&

            window.clearTimeout(this.serverTimeoutObj);

          this.timeoutObj = setTimeout(() => {

            // 这里发送一个心跳,后端收到后,返回一个心跳消息,

            this.ws.send("1");

            this.serverTimeoutObj = setTimeout(() => {

              this.ws.close();

            }, timeout);

          }, timeout);

        },

      };

      this.ws.onclose = () => {

        console.log("链接关闭", this.wsUrl);

        this.reconnect(this.wsUrl);

      };

      this.ws.onerror = () => {

        console.log("链接失败", this.wsUrl);

        this.reconnect(this.wsUrl);

      };

      this.ws.onopen = () => {

        // 心跳检测重置

        this.heartCheck.start();

      };

      this.ws.onmessage = (event) => {

        console.log(event, "webScoket心跳链接");

        if (

          event.data != "1" &&

          event.data != "链接成功" &&

          event.data.indexOf("newAutoOpenOrder") == -1

        ) {

        //获取后台的小铃铛的数量、及重新调取列表接口

          const data = JSON.parse(event.data);

          this.badgeValue = data.msgnum;

          this.getMessageList();

        }

        // 拿到任何消息都说明当前连接是正常的

        this.heartCheck.start();

      };

    },

    // 重新链接websocket

    reconnect(url) {

      if (this.lockReconnect) {

        return;

      }

      this.lockReconnect = true;

      // 没连接上会一直重连,设置延迟避免请求过多

      this.tt && window.clearTimeout(this.tt);

      this.tt = setTimeout(() => {

        this.createWebSocket(url);

        this.lockReconnect = false;

      }, 60000);

    },

    // 获取未读消息列表

    async getMarkallread() {

      const res = await markallread(this.loginInfo.userId);

      if (res && res.code == 200) {

        this.getMessageList();

      }

    },

    // 退出登录 清空WebSocket

    logout() {

      this.ws.onclose = () => { };

      this.ws.onerror = () => { };

      this.ws.close();

      window.clearTimeout(this.timeoutObj);

      window.clearTimeout(this.serverTimeoutObj);

      this.$router.push("/login");

    },

  },


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月30日 0

暂无评论

推荐阅读
  gYl4rku9YpWY   2024年05月17日   57   0   0 Vue
  onf2Mh1AWJAW   2024年05月17日   57   0   0 Vue
  3A8RnFxQCDqM   2024年05月17日   52   0   0 Vue
0yB7pUbXdkep