一文详解websocket在vue2中的封装使用

 更新时间:2023年03月08日 11:45:29   作者:梓恒  
这篇文章主要为大家介绍了一文详解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);
       }
     }
   }
 }

以上就是一文详解websocket在vue2中的封装使用的详细内容,更多关于vue2封装websocket的资料请关注脚本之家其它相关文章!

相关文章

  • vue配置font-awesome5的方法步骤

    vue配置font-awesome5的方法步骤

    这篇文章主要介绍了vue配置font-awesome5的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • vue+element-ui+axios多文件上传的实现并显示整体进度

    vue+element-ui+axios多文件上传的实现并显示整体进度

    这篇文章主要介绍了vue+element-ui+axios多文件上传的实现并显示整体进度,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • 详解Nuxt.js Vue服务端渲染摸索

    详解Nuxt.js Vue服务端渲染摸索

    本篇文章主要介绍了详解Nuxt.js Vue服务端渲染摸索,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • 在vue-cli3中使用axios获取本地json操作

    在vue-cli3中使用axios获取本地json操作

    这篇文章主要介绍了在vue-cli3中使用axios获取本地json操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • Vue拖拽组件开发实例详解

    Vue拖拽组件开发实例详解

    本文重点给大家介绍Vue拖拽组件开发实例,拖拽的原理是手指在移动的过程中,实时改变元素的位置即top和left值,使元素随着手指的移动而移动。对实例代码感兴趣的朋友跟随脚本之家小编一起学习吧
    2018-05-05
  • 前端虚拟滚动列表实现代码(vue虚拟列表)

    前端虚拟滚动列表实现代码(vue虚拟列表)

    前端的性能瓶颈那就是页面的卡顿,当然这种页面的卡顿包含了多种原因,下面这篇文章主要给大家介绍了关于前端虚拟滚动列表实现的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • element中Steps步骤条和Tabs标签页关联的解决

    element中Steps步骤条和Tabs标签页关联的解决

    这篇文章主要介绍了element中Steps步骤条和Tabs标签页关联的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • vue使用高德地图实现添加点标记和获取点击位置信息的示例代码

    vue使用高德地图实现添加点标记和获取点击位置信息的示例代码

    这篇文章主要介绍了vue使用高德地图实现添加点标记和获取点击位置信息的示例代码,文中补充介绍了高德vue-amap使用(一)标记点位获取地址及经纬度,本文结合示例代码给大家介绍的非常详细,需要的朋友参考下吧
    2024-01-01
  • vue项目发布有缓存正式环境不更新的解决方案

    vue项目发布有缓存正式环境不更新的解决方案

    vue项目每次发布新版本后,测试人员都要强制刷新才能更新浏览器代码来验证bug,下面这篇文章主要给大家介绍了关于vue项目发布有缓存正式环境不更新的解决方案,需要的朋友可以参考下
    2024-03-03
  • 在Vue中使用动态import()语法动态加载组件

    在Vue中使用动态import()语法动态加载组件

    在Vue中,你可以使用动态import()语法来动态加载组件,动态导入允许你在需要时异步加载组件,这样可以提高应用程序的初始加载性能,本文给大家介绍在Vue中使用动态import()语法动态加载组件,感兴趣的朋友一起看看吧
    2023-11-11

最新评论