前端封装WebSocket工具n

  1. Web API 提供的 WebSocket 类,封装一个 Socket 类
// socket.js
import modal from '@/plugins/modal'
const baseURL = import.meta.env.VITE_APP_BASE_WS;
const EventTypes = ['open', 'close', 'message', 'error', 'reconnect'];
const DEFAULT_CHECK_TIME = 55 * 1000; // 心跳检测的默认时间
const DEFAULT_CHECK_COUNT = 3; // 心跳检测默认失败重连次数
const DEFAULT_CHECK_DATA = { Type: 1, Parameters: ['alive'] }; // 心跳检测的默认参数 - 跟后端协商的
const CLOSE_ABNORMAL = 1006; // WebSocket非正常关闭code码class EventMap {deps = new Map();depend(eventType, callback) {this.deps.set(eventType, callback);}notify(eventType, event) {if (this.deps.has(eventType)) {this.deps.get(eventType)(event);}}
}class Socket extends WebSocket {heartCheckData = DEFAULT_CHECK_DATA;heartCheckTimeout = DEFAULT_CHECK_TIME;heartCheckInterval = null;heartCheckCount = DEFAULT_CHECK_COUNTconstructor(options, dep, reconnectCount = 0) {let _baseURL = baseURLconst { url, protocols, query = {}, greet = null, customBase = null } = options;const _queryParams = Object.keys(query).reduce((str, key) => {if (typeof query[key] !== 'object' && typeof query[key] !== 'function') {return str += str.length > 0 ? `&${key}=${query[key]}` : `${key}=${query[key]}`;} else {return str;}}, '');if (customBase) {_baseURL = customBase}super(`${_baseURL}${url}?${_queryParams}`, protocols);this._currentOptions = options;this._dep = dep;this._reconnectCount = reconnectCount;greet && Object.assign(this, {heartCheckData: greet})this.initSocket();}// 初始化WebSocketinitSocket() {// 监听webSocket的事件this.onopen = function (e) {this._dep.notify('open', e);this.heartCheckStart();}this.onclose = function (e) {this._dep.notify('close', e);// 如果WebSocket是非正常关闭 则进行重连if (e.code === CLOSE_ABNORMAL) {if (this._reconnectCount < this.heartCheckCount) {this._reconnectCount++;const _socket = new Socket(this._currentOptions, this._dep, this._reconnectCount);this._dep.notify('reconnect', _socket);} else {return modal.msgError('WebSocket重连失败, 请联系技术客服!');}}}this.onerror = function (e) {this._dep.notify('error', e);}this.onmessage = function (e) {// 如果后端返回的是二进制数据if (e.data instanceof Blob) {const reader = new FileReader()reader.readAsArrayBuffer(e.data)reader.onload = (ev) => {if (ev.target.readyState === FileReader.DONE) {this._dep.notify('message', ev.target?.result);}}} else {// 处理普通数据try {const _parseData = JSON.parse(e.data);this._dep.notify('message', _parseData);} catch (error) {console.log(error)}}}}// 订阅事件subscribe(eventType, callback) {if (typeof callback !== 'function') throw new Error('The second param is must be a function');if (!EventTypes.includes(eventType)) throw new Error('The first param is not supported');this._dep.depend(eventType, callback);}// 发送消息sendMessage(data, options = {}) {const { transformJSON = true } = options;let result = data;if (transformJSON) {result = JSON.stringify(data);}this.send(result);}// 关闭WebSocketcloseSocket(code, reason) {this.close(code, reason);}// 开始心跳检测heartCheckStart() {this.heartCheckInterval = setInterval(() => {if (this.readyState === this.OPEN) {let transformJSON = typeof this.heartCheckData === 'object'this.sendMessage(this.heartCheckData, { transformJSON });} else {this.clearHeartCheck();}}, this.heartCheckTimeout)}// 清除心跳检测clearHeartCheck() {clearInterval(this.heartCheckInterval);}// 重置心跳检测resetHeartCheck() {clearInterval(this.heartCheckInterval);this.heartCheckStart();}
}
// 默认的配置项
const defaultOptions = {url: '',protocols: '',query: {},
}export const useSocket = (options = defaultOptions) => {if (!window.WebSocket) return modal.msgWarning('您的浏览器不支持WebSocket, 请更换浏览器!');const dep = new EventMap();const reconnectCount = 0;return new Socket(options, dep, reconnectCount);
}
  1. 使用这个封装好的 useSocket 函数,以在 Vue3中使用为例
// xx.jsx or xx.vue
import { useSocket } from './socket.js'
const socket = ref(null) // WebSocket实例
const initWebSocket = () => {const options = {url: '/<your url>',query: {// something params},}socket.value = useSocket(options)socket.value.subscribe('open', () => {console.log('WebSocket连接成功!')const greet = 'hello'// 发送打招呼消息socket.value.sendMessage(greet)})socket.value.subscribe('close', reason => {console.log('WebSocket连接关闭!', reason)})socket.value.subscribe('message', result => {console.log('WebSocket接收到消息:', result)})socket.value.subscribe('error', err => {console.log('WebSocket捕获错误:', err)})socket.value.subscribe('reconnect', _socket => {console.log('WebSocket断开重连:', _socket)socket.value = _socket})
}
initWebSocket()
  1. debug 我们的心跳检测是否有效
// 测试心跳检测重连 手动模拟断开的情况
if (this._reconnectCount > 0) return;
const tempTimer = setInterval(() => {this.close();if (this._reconnectCount < 3) {console.log('重连');this._reconnectCount++;const _socket = new Socket(this._currentOptions, this._dep, this._reconnectCount);this._dep.notify('reconnect', _socket);} else {return clearInterval(tempTimer);}
}, 3 * 1000)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/78841.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP和UDP传输层协议

TCP&#xff08;Transmission Control Protocol&#xff09;和 UDP&#xff08;User Datagram Protocol&#xff09;是两种常见的传输层协议&#xff0c;它们在网络通信中发挥着不同的作用。二者在连接建立、可靠性、传输效率等方面存在显著差异&#xff0c;适用于不同的应用场…

空域伦理与AI自主边界的系统建构

在AI无人系统逐步参与城市空域治理的过程中&#xff0c;系统的“自主性”已不再仅是技术指标&#xff0c;而是直接影响合规性、安全性与社会接受度的伦理边界议题。AI决策系统是否拥有“强干预能力”&#xff1f;行为触发责任应归属何方&#xff1f;算法可否调优至“自我纠偏”…

在原生代码(非webpack)里使用iview的注意事项

最近公司在做一个项目&#xff0c;使用的框架是iview,使用过程中同事遇到一些问题&#xff0c;这些问题对于有些同学来说根本就不是问题&#xff0c;但总会有同学需要&#xff0c;为了帮助不太会用的同学快速找到问题&#xff0c;做了如下整理&#xff1a; 下载vue,iview.min.j…

java代码混淆

生成jar的时候混淆 目前最常用的Proguard,网上有很多介绍的文章&#xff0c;这种安全性较低 对已经生成的jar进行加密 加密库:https://github.com/li571312729/classfinal 测试对jar进行加密 加密后如果正常调用的话会失败 加密后jar反编译查看不到代码 使用密码才能调用机…

【Linux】第十三章 访问Linux文件系统

目录 1. 存储设备是什么&#xff1f;怎么理解分区和格式化&#xff1f; 2. 文件系统是什么&#xff1f; 3. 挂载是什么&#xff1f;挂载点是什么&#xff1f; 4. 怎么理解块设备&#xff1f; 5. 在SATA附加存储中&#xff0c;第一磁盘上的第一个分区和第二磁盘的第二个分区…

MCP 服务器搭建【stdio 类型】实现上市公司年报查询总结,配合 Cherry Studio使用简单

代码解释 这段 Python 代码的主要功能是搭建一个基于 FastAPI 的 MCP 服务器,用于处理通过股票代码查询上市公司年报的请求,实现服务器向客户端的实时消息推送。以下是对代码各部分的详细解释: 完整代码+使用 Cherry Studio 调用 MCP 服务器的方法,放在文章最后了 1. 导…

第六节:软件安装

理论知识 软件安装的方式&#xff1a;在 Linux 系统中&#xff0c;常见的软件安装方式有源码安装、在线安装、deb 包安装、RPM 包安装、使用 Snap 管理软件包等。不同的安装方式适用于不同的软件和场景。源码安装&#xff1a;源码安装是指从软件的源代码开始&#xff0c;进行编…

ubantu部署yolov5(第四集:模型加速)

参考链接&#xff1a; GitHub - ultralytics/yolov5: YOLOv5 &#x1f680; in PyTorch > ONNX > CoreML > TFLite TFLite,ONNX,CoreML,TensorRT Export -Ultralytics YOLO Docs 使用Neural Magic 的 DeepSparse 部署YOLOv5 -Ultralytics YOLO 文档 sparseml/inte…

flutter 专题 五十六 Google 2020开发者大会Flutter专题

由于疫情的原因&#xff0c;今年的Google 开发者大会 (Google Developer Summit) 在线上举行&#xff0c;本次大会以“代码不止”为主题&#xff0c;全面介绍了产品更新以及一系列面向本地开发者的技术支持内容。我比较关注的是移动开发&#xff0c;在本次大会上&#xff0c;关…

开源模型应用落地-qwen模型小试-Qwen3-8B-快速体验-pipeline方式(二)

一、前言 阿里云最新推出的 Qwen3-8B 大语言模型,作为国内首个集成“快思考”与“慢思考”能力的混合推理模型,凭借其 80 亿参数规模及 128K 超长上下文支持,正在重塑 AI 应用边界。该模型既可通过轻量化“快思考”实现低算力秒级响应,也能在复杂任务中激活深度推理模式,以…

「动态规划::背包」01背包 / AcWing 2(C++)

概述 AcWing 2&#xff1a; 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的体积是 v[i]&#xff0c;价值是 w[i]。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 第一…

Java 中的 设计模式详解

一&#xff1a;设计模式概述 &#xff08;1&#xff09;概述 &#xff08;2&#xff09;分类 创建型 行为型 结构型 二&#xff1a;软件设计模式 2.1 开闭原则 &#xff08;1&#xff09;定义 在程序需要进行拓展的时候&#xff0c;不能修改原有代码 使用到接口和抽象类&#x…

阿里qiankun微服务搭建

主服务 chat vue3 ts vite 子服务 ppt react 18 vite 子服务 agent 主服务 npm i vite-plugin-qiankun mian.ts import ./style/base.scss import virtual:svg-icons-register import { createApp } from vue import { createPinia } from piniaimport App from ./App.vue im…

安装WSL2,配置Ubuntu图像化界面

目录 一、前言二、安装WSL三、安装图像化界面四、参考 一、前言 Windows 子系统下的 Linux 子系统&#xff08;WSL&#xff0c;Windows Subsystem for Linux&#xff09;是微软推出的一项功能&#xff0c;允许用户在 Windows 系统中原生运行 Linux 环境&#xff0c;无需安装虚…

图像畸变-径向切向畸变实时图像RTSP推流

实验环境 注意&#xff1a;ffmpeg进程stdin写入两张图片的时间间隔不能太长&#xff0c;否则mediamtx会出现对应的推流session超时退出。 实验效果 全部代码 my_util.py #进度条 import os import sys import time import shutil import logging import time from datetime i…

Redis Sentinel 和 Redis Cluster 各自的原理、优缺点及适用场景是什么?

我们来详细分析下 Redis Sentinel (哨兵) 和 Redis Cluster (集群) 这两种方案的原理和使用场景。 Redis Sentinel (哨兵) 原理: Sentinel 本身是一个或一组独立于 Redis 数据节点的进程。它的核心职责是监控一个 Redis 主从复制 (Master-Slave) 架构。多个 Sentinel 进程协同…

基于机器学习的电影票房预测

目录 摘 要(完整下载链接附在文末) Abstract 1 绪 论 1.1 研究背景概述 1.2 国内外相关领域研究进展 1.3 电影票房预测技术概览 1.3.1 利用人口统计学特征的方法 1.3.2 基于机器学习的预测模型 2 机器学习相关理论介绍与分析 2.1 机器学习算法理论 2.1.1卷积…

SVMSPro平台获取HTTP-FLV规则

SVMSPro平台获取HTTP-FLV规则 HTTP-FLV的服务端口为&#xff1a;53372&#xff0c;如需要公网访问需要开启这个端口 这里讲的是如何获取长效URL&#xff0c;短效&#xff08;时效性&#xff09;URL也支持&#xff0c;下回讲 一、如何获取HTTP-FLV实时流视频 http://host:po…

ARM架构的微控制器总线矩阵

在 ARM 架构的微控制器&#xff08;MCU&#xff09;中&#xff0c;总线矩阵&#xff08;Bus Matrix&#xff09; 是总线系统的核心互连结构&#xff0c;负责协调多个主设备&#xff08;如 CPU、DMA、以太网控制器等&#xff09;对多个从设备&#xff08;如 Flash、SRAM、外设等…

AI赋能金融:智能投顾、风控与反欺诈的未来

AI赋能金融&#xff1a;智能投顾、风控与反欺诈的未来 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 AI赋能金融&#xff1a;智能投顾、风控与反欺诈的未来摘要引言一、智能投顾&#xff1a;从经验驱动到人机协同…