socket实例 挂载到全局

为方便梳理,请忽略typescript

  1. # main.ts
  2. import {createApp} from 'vue'
  3. import App from './App.vue'
  4. import {socket} from "@/xihu/socket"
  5. import router from "@/xihu/router"
  6. const app = createApp(App);
  7. app.use(router).mount('#root');
  8. // 全局挂载
  9. app.config.globalProperties.$socket = socket;

Socket封装(断线重连)

这个WebSocket类封装了WebSocket的连接、重连、发送数据等方法。

connect方法中,它会连接WebSocket,并绑定相关事件监听。

onclose事件中,它会调用reconnect方法进行重连。

reconnect方法会在一定时间内重连,并且重连的时间间隔会越来越长,最大重连次数达到设定值后就不再重连。

这样就实现了一个可以断线重连的WebSocket连接。

我们可以在vue应用中使用这个类来进行WebSocket通信,并处理可能出现的网络断开重连情况。

  1. # socket.ts
  2. // @ts-nocheck
  3. export default class Socket {
  4. constructor(url, protocols) {
  5. this.url = url
  6. this.protocols = protocols
  7. this.ws = null
  8. this.reconnectTimeout = 1000
  9. this.maxReconnectTimes = 5
  10. }
  11. connect() {
  12. this.ws = new WebSocket(this.url, this.protocols)
  13. this.ws.onopen = () => {
  14. console.log('WebSocket连接成功')
  15. this.reconnectTimes = 0
  16. }
  17. this.ws.onclose = () => {
  18. console.log('WebSocket断开连接')
  19. this.reconnect()
  20. }
  21. this.ws.onerror = err => {
  22. console.log('WebSocket连接出错', err)
  23. }
  24. }
  25. reconnect() {
  26. if (this.reconnectTimes < this.maxReconnectTimes) {
  27. setTimeout(() => {
  28. this.connect()
  29. this.reconnectTimes++
  30. }, this.reconnectTimeout)
  31. this.reconnectTimeout *= 2
  32. } else {
  33. console.log('WebSocket重连超过最大次数,放弃重连')
  34. }
  35. }
  36. // 消息发送
  37. msg(param) {
  38. if (param === 'heartbeat') {
  39. this.ws.send(param);
  40. } else {
  41. this.ws.send(JSON.stringify(param));
  42. }
  43. }
  44. // 延迟发送
  45. timeout(param) {
  46. setTimeout(() => {
  47. this.msg(param);
  48. }, 2000)
  49. }
  50. send(param) {
  51. if (this.ws.readyState === this.ws.OPEN) {
  52. this.msg(param);
  53. } else if (this.ws.readyState === this.ws.CONNECTING) {
  54. this.timeout(param);
  55. } else {
  56. this.timeout(param);
  57. }
  58. }
  59. }

实例化socket

通过type关键字,分发数据,并且通过pinia(vuex)存储实时数据

在消息回调函数,处理返回的数据,使用type关键字对应各种推送事件,比如:实时设备告警、地图显示用户坐标等等...

  1. // @ts-nocheck
  2. import {createPinia} from 'pinia';
  3. import {useAlarm} from '@/store/alarm';
  4. // 状态管理
  5. export const pinia = createPinia();
  6. export const store = useAlarm(pinia);
  7. export function wsInit(callback) {
  8. const url = 'ws://api.xx.cn';
  9. const init = new Socket(url);
  10. // 连接 WebSocket
  11. init.connect();
  12. // 监听 WebSocket
  13. init.ws.onmessage = function (ev) {
  14. if (ev && ev.data && ev.data.indexOf('subscribe') > -1) {
  15. console.log('subscribe->', ev.data);
  16. } else if (ev && ev.data) {
  17. var data = eval('(' + ev.data + ')');
  18. callback(data);
  19. }
  20. };
  21. return init;
  22. }
  23. // 消息回调
  24. export const socket = wsInit((data) => {
  25. switch (data.type) {
  26. case 1:
  27. store.setType1(data);
  28. break;
  29. case 2:
  30. store.setType2(data.message);
  31. break;
  32. }
  33. });

状态管理

  1. import {defineStore} from 'pinia'
  2. export const useAlarm = defineStore('user', {
  3. state:()=>({
  4. type1:{},
  5. type2:{},
  6. }),
  7. getters:{
  8. getType1: (state) => state.type1,
  9. getType2: (state) => state.type2,
  10. },
  11. actions:{
  12. setType1(payload: any) {
  13. this.type1 = payload;
  14. },
  15. setType2(payload: any) {
  16. this.type2 = payload;
  17. },
  18. },
  19. })

在页面中,使用数据(pinia)

  1. import { watch, computed, onMounted, getCurrentInstance} from 'vue'
  2. import {useAlarm} from "@/xihu/store/alarm";
  3. const store = useAlarm();
  4. // 还记得全局挂载的`$socket`吧,这样使用
  5. const ctx: any = getCurrentInstance();
  6. const {$socket} = ctx.appContext.config.globalProperties;
  7. onMounted(() => {
  8. // 列表数据 -- 通过给`websocket`发送`{"cmd":"1"}`实现数据交互
  9. $socket.send({cmd: 1});
  10. });
  11. const click = ()=>{
  12. // 其他数据 -- 点击列表的某一项,根据参数获取数据
  13. $socket.send({cmd: 2,extras:{id:123}});
  14. }
  15. // 第一种 监听方式:
  16. const type1 = computed(() => store.type1);
  17. watch(type1, (message: any) => {
  18. console.log('/computed/watch/', message);
  19. }, {deep: true});
  20. // 第二种 监听方式:
  21. store.$subscribe(({events}: any, state) => {
  22. if (events.key === 'type1') {
  23. console.log('/$subscribe/', state.type1);
  24. }
  25. });

大多数情况,数据是后台主动推送的,比如:告警数据,这也是使用websocket的主要原因

ai问答:vue3+pinia+WebSocket 封装断线重连(实战)的更多相关文章

  1. webSocket使用心跳包实现断线重连

    首先new一个webscoket的连接 let noticeSocketLink = new WebSocket(‘webSocket的地址’) 这里是连接成功之后的操作 linkNoticeWebs ...

  2. js websocket断线重连

    js websocket断开重连实例代码,请根据自己需求做出相应改动Vue中使用websocket $(function() { var lockReconnect = false;//避免重复连接 ...

  3. uniapp小程序webSocket封装使用

    目录 1,前言 2,代码实现 3,使用 3.1,初始化 3.2,发送消息 3.3,接收消息 1,前言 最近在做IOT的项目,里面有个小程序要用到webSocket,借这个机会,封装了一个uniapp小 ...

  4. 理解WebSocket心跳及重连机制(五)

    理解WebSocket心跳及重连机制 在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件.这样会有:服务器会继续向客户端发送多余的 ...

  5. 【简记】前端对接WebSocket与心跳重连

    前言 最近又在忙着开发别的模块,其中包含了即时通讯这一块,上一次做即时通讯时还是去年年底,一时间代码都在自己的笔记本里,还没带--这里就记录一下前端对接WebSocket的实现,包含心跳重连,简记之. ...

  6. EasyRTMP+EasyRTSPClient实现的多路(支持断线重连)RTSP转RTMP直播推流工具

    本文转自EasyDarwin开源团队成员Kim的博客:http://blog.csdn.net/jinlong0603/article/details/73441405 介绍 EasyRTMP是Eas ...

  7. 微信小程序使用原生WebSokcet实现断线重连及数据拼接

    以前做小程序为了应急找了个插件去链接WebSokcet,文章传送门. 回过头在新项目中再次使用时出现了些许问题,不一一赘述.遂决定好好用一下原生的WebSokcet. 一.说明 1.小程序原生的Web ...

  8. java-websocket客户端 断线重连 注入Service问题

    java版客户端: 使用开源项目java-websocket, github地址: https://github.com/TooTallNate/Java-WebSocket github上有很多示例 ...

  9. 关于socket tcp 断线重连

    这个问题困扰过我几次,都没有来得及研究,今天研究一下. 首先写一个最简易的socket tcp程序,连接成功后再关闭服务器然后再用客户端各种操作看是什么情况 测试表明 (1)客户端已经连接,当服务端关 ...

  10. netty4 断线重连

    转载:http://www.tuicool.com/articles/B7RzMbY 一 实现心跳检测 原理:当服务端每隔一段时间就会向客户端发送心跳包,客户端收到心跳包后同样也会回一个心跳包给服务端 ...

随机推荐

  1. gstreamer样例

    #!/bin/bash xrandr -s 0 --output DSI-1 xrandr -s 0 --output HDMI-1 xrandr --fb 1024x600 --output DSI ...

  2. MySQL增加多用户及数据库

    登录MYSQL(有ROOT权限),这里以ROOT身份登录: @>mysql -u root -p @>密码 首先为用户创建一个数据库(yc): mysql>create databa ...

  3. Oracle入门- 数据库操作相关脚本

    1. 创建表 1 CREATE TABLE SYS_NOTICE 2 ( 3 GUID CHAR(32) NOT NULL, 4 TITLE VARCHAR2(128) NOT NULL 5 ); 6 ...

  4. 11. ASCII, unicode, utf-8, gbk的区别

    这是几种编码方式 ASCII是包含英文字母数字特殊字符等, 长度是1字节, 前128个是基础ASCII码, 128个以后是扩展ASCII码 GBK是国标扩展码, 长度2字节, 表示汉字以及各少数民族语 ...

  5. boost编译指定python版本号

    1.执行如下 bootstrap 语句,会在目录下生成 project-config.jam 文件 .\bootstrap --with-python="C:\Users\yzy\Anaco ...

  6. 信创国产化,试试 Solon v2.2.2

    Solon 是一个高效的 Java 应用开发框架:更快.更小.更简单.它不是 Spring.没有用 Servlet.也无关 JavaEE,是一个有自己接口标准的开放生态.可以为应用软件国产化提供支持, ...

  7. [SUCTF 2019]EasySQL 1

    这个题目搞了我好久,由于本人基础不扎实,试了好多方法,只发现有三种情况 Nonono.无返回结果和有返回 然后使用了新学习的堆叠注入,得到了数据库名和表名 想要查看Flag表的字段内容也查看不了 这里 ...

  8. 音频的价值、AI Codec 的意义与算法能力的边界丨一期一会 • 音频工程师专场

    前言 音频技术发展到今天,经历了从模拟音频到数字音频到历程.国际音频工程师协会创建于 1948 年,中国数字音频技术起步相对较晚,长期被国外组织和公司垄断.随着中国的不断发展.科技日益进步,经过近三十 ...

  9. Redis 缓存雪崩 |击穿 |穿透 概念及解决方案

    一.雪崩 1.概念  指某一时间段,缓存集中过期失效,无数的请求绕开缓存,直接访问数据库. 2.解决方案 让redis数据永不过期,这种方式最可靠的.最安全的,但占用空间,内存消耗大,并且不能保持数据 ...

  10. PHP的序列化和反序列化

    PHP序列化 什么是PHP序列化 serialize() //将一个对象转换成一个字符串 unserialize() //将字符串还原成一个对象 通过序列化与反序列化我们可以很方便的在PHP中进行对象 ...