websocket在vue2中如何封装使用

作者:有用网 阅读量:253 发布时间:2023-10-16
关键字 websocket

这篇文章主要讲解了“websocket在vue2中如何封装使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“websocket在vue2中如何封装使用”吧!

    websocket在vue2中的封装使用

    先说需求: 页面中有websocket连接,进入的时候发送参数到后端,后端发送消息, 离开页面时发送参数至后端,后端停止发送消息,不得断开连接, 下一次进入时页面时不用再次连接。

    实现思路:

    • 因为是全局连接一个websocket,所以这里采用单例模式

    • 也是因为封装的原因,页面中肯定是直接拿不到onmessage中返回的数据, 所以这里采用发布订阅模式来做

    完整代码在最后,不想看我废话的可以直接扒拉了

    步骤

    步骤就是: 连接,页面发送消息,接收消息,over ~

    首先定义连接websocket的方法

     export default class SocketService {
         constructor(url){
             this.url = url
         },
         connect() {
             //判断浏览器是否支持websocket
             if (!window.WebSocket) {
               return console.log("您的浏览器不支持WebSocket");
             }
             url,
            //连接websocket
             this.ws = new WebSocket(this.url);
             //监听websocket各种状态
             this.ws.onopen = () => {};
             this.ws.onclose = () => {};
             this.ws.onerror = () => {};
             this.ws.onmessage = (e) => {};
         }
     }

    我们先让socket连接上叭

     export default class SocketService {
         constructor(url, againConnect = true){
             this.url = url
             this.againConnect = againConnect;
         },
           ws = null;         // 和服务端连接的socket对象
           url;               //地址
           againConnect;      //标识断开是否重连
           connected = false; // 标识是否连接成功
           sendRetryCount = 0; // 记录重试的次数
           connectRetryCount = 0; // 重新连接尝试的次数
         connect() {
             //判断浏览器是否支持websocket
             if (!window.WebSocket) {
               return console.log("您的浏览器不支持WebSocket");
             }
             url,
            //连接websocket
             this.ws = new WebSocket(this.url);
             //监听websocket各种状态
             this.ws.onopen = () => {
                 //连接上后所有标识清零
                 this.connected = true;
                 this.connectRetryCount = 0;
             };
             this.ws.onclose = () => {
                 //连接关闭
                 this.connected = false;
                 this.connectRetryCount++;
                 if (this.againConnect) {
                     //重连
                     setTimeout(() => {
                       this.connect();
                     }, 500 * this.connectRetryCount);
                   } else {
                     //不重连的操作
                      sessionStorage.clear();
                      localStorage.clear();
                      message.error("登录超时");
                      router.push("/");
                   }
             };
             this.ws.onerror = () => {
                 //连接失败
                   this.connected = false;
                   this.connectRetryCount++;
                   if (this.againConnect) {
                     setTimeout(() => {
                       this.connect();
                     }, 500 * this.connectRetryCount);
                   }
             };
             this.ws.onmessage = (e) => {
                 console.log(e)
             };
         },
         unSubscribe() {}
         send(){
             //发送消息的方法
         }
     }

    那么我们要怎么给后端发送消息呢,发送了消息之后我们又该怎样才能在页面中接收到消息呢?

    在send方法中接收一个回调函数,

    在message中调用,

     subscribeList = {}; //记载回调函数
     idList = [];
     send(data, callback) {
         //判断此时有没有ws
         if (!this.ws) {
           this.connect();
           this.send(data, callback);
         } else {
           // 判断此时此刻有没有连接成功
           if (this.connected) {
             this.sendRetryCount = 0;
             this.ws.send(JSON.stringify(data));
             if (data.type === "sub") {
               //存储id
               this.idList.push(data.id);
               //存储回调函数,
               if (!this.subscribeList[data.id]) {
                 this.subscribeList[data.id] = [callback];
               } else {
                 this.subscribeList[data.id].push(callback);
               }
             }
           } else {
             this.sendRetryCount++;
             setTimeout(() => {
               this.send(data, callback);
             }, this.sendRetryCount * 500);
           }
         }
       }
     connect(){
         ......
         this.ws.onmessage = (e) => {
           let { payload, requestId, type } = JSON.parse(e.data);
           if (type === "error") {
             console.log("出错了");
           }
           if (this.subscribeList[requestId]) {
             if (type === "complete") {
               console.log("完成了");
             } else if (type === "result") {
               this.subscribeList[requestId].forEach((item) =>
                 item.call(this, payload)
               );
             }
           }
         };
     }
     //销毁回调函数
       unSubscribe() {
         //停止消息发送
         this.idList.forEach((item) => {
           this.send({ id: item, type: "unsub" });
           delete this.subscribeList[item];
         });
         this.idList = [];
      }
    • sub标识发送消息, unsub标识停止发送消息

    • id为事件的标识符

    现在解决了页面中接收消息的问题,那么怎么保证离开页面,回到页面,使用的是同一个websocket呢,如果实例化这个类的话,那么每次进入都会实例化SocketService,

    es6的class中有取值函数和存值函数, 具体使用请看这里:

    Class 的基本语法 - ES6 教程 - 网道 (wangdoc.com)

     instance = null;
     static get Instance() {
         if (!this.instance) {
           this.instance = new SocketService(false);
         }
         return this.instance;
      }
    • 使用getter,来拿取class中的instance,拿取的时候设置拦截该行为,判断instance有没有值,没有值就实例化SocketService给instance,返回instance,

    页面中使用方式

     import SocketService from "@/websocket/websocket";
     mounted() {
         this.ws = SocketService.Instance;
         this.ws.send(
           {
             id: "11111",
             topic: "/xxx/xxx",
             parameter: {},
             type: "sub",
           },
           this.Callback
         );
     }
     destroyed() {
         this.ws.unSubscribe();
     },
     methods:{
         Callback(data) {
               console.log(data);
         },
     }

    在vue中的封装

     export default class SocketService {
       constructor(againConnect = true, url) {
         this.url = url;
         this.againConnect = againConnect;
       }
       instance = null;  //页面中使用的SocketService实例
       ws = null; // 和服务端连接的socket对象
       url; //地址
       againConnect;     //断开是否重连
       connected = false; // 标识是否连接成功
       sendRetryCount = 0; // 记录重试的次数
       connectRetryCount = 0; // 重新连接尝试的次数
       //单例模式保证只有一个SocketService实例
       static get Instance() {
         if (!this.instance) {
             this.url = '......'
           this.instance = new SocketService(false, url);
         }
         return this.instance;
       }
       //  定义连接服务器的方法
       connect() {
         // 这里判断你的浏览器支不支持websocket
         if (!window.WebSocket) {
           return console.log("您的浏览器不支持WebSocket");
         }
         this.ws = new WebSocket(this.url);
         //连接上了
         this.ws.onopen = () => {
           this.connected = true;
           // 重置重新连接的次数
           this.connectRetryCount = 0;
         };
           //连接关闭了,设置标识值为false,
         this.ws.onclose = () => {
           this.connected = false;
           this.connectRetryCount++;
           if (this.againConnect) {
             setTimeout(() => {
               this.connect();
             }, 500 * this.connectRetryCount);
           } else {
             sessionStorage.clear();
             localStorage.clear();
             message.error("登录超时");
             router.push("/");
           }
         };
         this.ws.onerror = () => {
           console.log("socket连接失败");
           this.connected = false;
           this.connectRetryCount++;
           if (this.againConnect) {
             setTimeout(() => {
               this.connect();
             }, 500 * this.connectRetryCount);
           }
         };
         this.ws.onmessage = (e) => {
           let { payload, requestId } = JSON.parse(e.data);
           if (this.subscribeList[requestId]) {
               this.subscribeList[requestId].forEach((item) =>
                 item.call(this, payload)
               );
             }
         };
       }
       //销毁回调函数
       unSubscribe() {
         //停止消息发送
         this.idList.forEach((item) => {
           this.send({ id: item, type: "unsub" });
           delete this.subscribeList[item];
         });
         this.idList = [];
       }
       subscribeList = {}; //记载回调函数
       idList = [];
       // 发送数据的方法
       send(data, callback) {
         //判断此时有没有ws
         if (!this.ws) {
           this.connect();
           this.send(data, callback);
         } else {
           // 判断此时此刻有没有连接成功
           if (this.connected) {
             this.sendRetryCount = 0;
             this.ws.send(JSON.stringify(data));
             if (data.type === "sub") {
               //存储id
               this.idList.push(data.id);
               //存储回调函数,
               if (!this.subscribeList[data.id]) {
                 this.subscribeList[data.id] = [callback];
               } else {
                 this.subscribeList[data.id].push(callback);
               }
             }
           } else {
             this.sendRetryCount++;
             setTimeout(() => {
               this.send(data, callback);
             }, this.sendRetryCount * 500);
           }
         }
       }
     }

    #发表评论
    提交评论