uniapp自定义websocket类实现socket通信、心跳检测、连接检测、重连机制
uniapp自定义websocket类实现socket通信、心跳检测、检测连接、重连机制,仿vue-socket插件功能实现发送序列号进行连接检测,发送消息时42【key,value】格式,根据后端返回数据和需要接收到的数据做nsend与onSocketMessage的修改
//使用socket类this.socket = new websocket({url: chatUrl,onOpen: (res) => {this.socket?.nsend({type: "bind",fromid: uni.getStorageSync("project_user").uid})uni.$on("message", function(data) {that.recvMsg(data)})console.log('onOpen', res)},onClose: (res) => {console.log('onClose', res)},onRdFinsh: (res) => {console.log('onRdFinsh', res)}})
import {publish,subscribe,unsubscribe
} from 'pubsub-js'
import {isArray
} from "@/utils/validate"const noop = function() {};
class Socket {//心跳检测定时器static stopTime = 0;//每25s发送报文给服务端监听连接是否正常static sendInterval = 0;//服务端监听连接异常时提示并进行socket重连static isCommunication = false;//连接中出错调用心跳检测方法的定时器static errorNr = '';//websocket已连接数static concatCount = 0;//连接后连接设备次数(用于拼接传输序号42后的数字)static sendTag = 0//pc端emit发送消息有回调函数时加入static isCallback = ["leave", "join"]//连接或断连publish相应isCallback数组内的值给客户端响应static sendKey = "";//new Socket时执行构造方法,对参数默认值进行初始化constructor({url = '',onOpen = noop,onMsg = noop,onClose = noop,onError = noop,onReload = noop,onRdFinsh = noop,maxInterValCount = 10,interValTime = 2000,...args} = {}) {this.isRconnectIng = false; //是否处于重连状态this.waiting = Promise.resolve(false); //心跳检查必须等待重连完成后this.waitDep = []; //等待时收集依赖的容器this.SocketTask = {nsend: noop,hbDetection: noop,nclose: noop,nrconnect: noop,isconnect: false,uniColse: false,maxInterValCount,interValTime,InterValCount: 0,eventPatch: null,url,onOpen,onMsg,onClose,onError,onReload,onRdFinsh,extra: args};//为对象提供连接方法this._EventDispath(this.SocketTask);//初始化websocketthis.initChat(this.SocketTask, this.SocketTask.extra);return this.SocketTask;}set CONCATCOUNT(value) {Socket.concatCount = value;if (value > 0) this._notify();}get CONCATCOUNT() {return Socket.concatCount}/*** 每25s给服务端发送一次数据,确保连接未断开*/initSendTime() {Socket.sendInterval = setInterval(() => {if (Socket.isCommunication) {uni.showToast({icon: 'none',title: '网络异常',duration: 2000})this.SocketTask.nrconnect()} else {Socket.isCommunication = truethis.SocketTask.nsend(2)}}, 25000)subscribe("number", function(msg, data) {Socket.isCommunication = false})}//销毁定时器destroySend() {clearTimeout(Socket.errorNr)clearTimeout(Socket.stopTime);clearInterval(Socket.sendInterval)unsubscribe("number")}/*** 仅供内部使用,通知所有收集到的依赖*/_notify() {for (let i = 0; i < this.waitDep.length; i++) {this.waitDep[i].call(this.SocketTask);}this.waitDep = [];}/*** 仅供内部使用,确认当前是否连接成功,收集依赖*/_chunkConnect(fn) {//没有连接时收集起来,当连接成功时开始发送命令等操作if (Socket.concatCount > 0) {fn();} else {this.waitDep.push(fn);}}/*** 仅供内部使用,事件注册*/_EventDispath({onReload} = {}) {let SocketTask = this.SocketTask;let events = {onOpen: [],onMsg: [],onClose: [],onError: [],onReload: [],onRdFinsh: [],}SocketTask.hbDetection = () => {this.hbDetection()}//适配后端websocket发送请求数据//vue-socket-io 传入的是数组,第一位为key值SocketTask.nsend = (key, value) => {let that = thisthis._chunkConnect(() => {let data = "42"//web端连接或断开连接的时候传入420 421if (Socket.isCallback.includes(key)) {//收集当前连接的命令key值,等待返回响应时传递给客户端处理逻辑Socket.sendKey = key//421 422 ··· 依次递增data += Socket.sendTagSocket.sendTag++}if (value) {data += JSON.stringify([key, value])} else {//特殊情况,当想要发送的请求不为42【key,value】格式时,key为客户端代码发送传入的值data = key + ""}uni.sendSocketMessage({//pc端emit事件有发送完毕回调函数时后端会需要有多一位数字的判断,并且返回时也会产生eg:420 -》 430// 没有回调函数时发送和接收命令前面都是42data: data,complete(e) {},})})}SocketTask.nclose = t => {this.destroySend()this._chunkConnect(() => {SocketTask.uniColse = true;uni.closeSocket();})}SocketTask.nrconnect = t => {this._chunkConnect(() => {this.waiting = new Promise(async (resolve) => {uni.closeSocket();let reloadStatus = false;try {const res = await this.initChat(SocketTask, SocketTask.extra);reloadStatus = res;} catch (e) {}onReload.call(SocketTask, reloadStatus, SocketTask);SocketTask.eventPatch.dispatchEvent('onReload', reloadStatus);resolve(reloadStatus);})})}function EventDispatcher() {this.events = events;}for (let key in events) {//绑定监听方法到EventDispatcher方法原型中EventDispatcher.prototype[key] = function(handler) {if (typeof handler != 'function') return;this.events[key].push(handler)}}//调用监听方法 监听连接状态EventDispatcher.prototype.dispatchEvent = function(type, msg) {let evenArr = this.events[type];if (evenArr.length > 0) {for (let i = 0; i < evenArr.length; i++) {evenArr[i].call(SocketTask, msg, SocketTask);}}}SocketTask.eventPatch = new EventDispatcher();}/*** 心跳检测*/async hbDetection() {const SocketTask = this.SocketTask;if (SocketTask.uniColse) {return false;}clearTimeout(Socket.stopTime);if (!SocketTask.isconnect) { //未连接则启动连接if (SocketTask.maxInterValCount > SocketTask.InterValCount) {Socket.stopTime = setTimeout(async () => {try {const R_result = await this.waiting;if (R_result) return;this.isRconnectIng = true;const openResult = await this.initChat(SocketTask, SocketTask.extra);if (openResult) {SocketTask.InterValCount++;return;}return this.hbDetection();} catch (e) {return this.hbDetection();}}, SocketTask.interValTime)} else {SocketTask.onRdFinsh.call(SocketTask, SocketTask.maxInterValCount, SocketTask);SocketTask.eventPatch.dispatchEvent('onRdFinsh', SocketTask.maxInterValCount);}}}/*** websocket监听事件*/SocketEvents({onOpen,onMsg,onClose,onError,onReload,} = {}) {return new Promise((resolve, reject) => {const SocketTask = this.SocketTask;uni.onSocketOpen(res => {this.CONCATCOUNT += 1;this.isRconnectIng = false;SocketTask.isconnect = true;Socket.sendTag = 0Socket.sendKey = ""SocketTask.InterValCount = 0;SocketTask.uniColse = false;resolve(true);this.initSendTime()onOpen.call(SocketTask, res, SocketTask);SocketTask.eventPatch.dispatchEvent('onOpen', res)})//适配服务器端返回的消息格式uni.onSocketMessage(msg => {let serialNumber = 0let arrayIndex = msg.data.indexOf("[")let objIndex = msg.data.indexOf("{")//判断返回值是纯数字或json格式let dataStart = arrayIndex != -1 && objIndex != -1 ?(arrayIndex < objIndex ? arrayIndex : objIndex) :(arrayIndex == -1 ? objIndex : arrayIndex)if (dataStart == -1) {serialNumber = msg.data.substring(0)publish("number", serialNumber)} else {serialNumber = msg.data.substring(0, dataStart)let jsonData = JSON.parse(msg.data.substring(dataStart))//判断是否为连接事件if (serialNumber == `43${Socket.sendTag - 1}`) {publish(Socket.sendKey, jsonData[0])} else if (isArray(jsonData)) {publish(jsonData[0], jsonData[1])}}onMsg.call(SocketTask, msg, SocketTask);SocketTask.eventPatch.dispatchEvent('onMsg', msg)})uni.onSocketClose(async err => {this.destroySend()SocketTask.isconnect = false;SocketTask.InterValCount = 0;//微信小程序 连接失败会自动关闭连接,返回false给心跳监测方法resolve(false);if (!this.isRconnectIng) {this.hbDetection();}onClose.call(SocketTask, err, SocketTask);SocketTask.eventPatch.dispatchEvent('onClose', err);})uni.onSocketError(err => {this.destroySend()Socket.errorNr = setTimeout(() => {this.hbDetection()}, 3000)onError.call(SocketTask, err, SocketTask);SocketTask.eventPatch.dispatchEvent('onError', err)})})}/*** 开始初始化chat*/initChat({url,onOpen,onMsg,onClose,onError,onReload} = {}, args) {return new Promise(async (resolve, reject) => {try {await this.connectSocket(url, args);let res = await this.SocketEvents({onOpen,onMsg,onClose,onError,onReload,})resolve(res);} catch (e) {console.log('initChat', e)reject();}})}/*** 连接webSocket*/connectSocket(url, args) {return new Promise((resolve, reject) => {uni.connectSocket({url,success: () => {resolve();},fail: err => {reject();},...args})})}
}
export default Socket
相关文章:
uniapp自定义websocket类实现socket通信、心跳检测、连接检测、重连机制
uniapp自定义websocket类实现socket通信、心跳检测、检测连接、重连机制,仿vue-socket插件功能实现发送序列号进行连接检测,发送消息时42【key,value】格式,根据后端返回数据和需要接收到的数据做nsend与onSocketMessage的修改 //使用socket…...
Hive UDTF之explode函数、Lateral View侧视图
Hive UDTF之explode函数 Hive 中的 explode() 函数是一种用于处理数组类型数据的 User-Defined Table-Generating Function (UDTF)。它将数组拆分成多行,每个数组元素对应生成的一行数据。这在处理嵌套数据结构时非常有用,例如处理 JSON 格式的数据。 …...
智慧公厕打造智慧城市新标杆
公共厕所作为城市基础设施的重要组成部分,直接关系到市民的生活品质和城市形象。传统的公厕管理方式存在着许多问题,如环境脏乱、清洁不及时等,给市民带来了诸多不便和不满。而智慧公厕作为一种全新的管理模式,通过物联网、大数据…...
字节发布文生图模型PuLID:高效身份ID特征定制,单张图像克隆AI虚拟分身
前言 字节研究团队近日提出了一种新型的文生图身份ID定制方法PuLID(Pure and Lightning ID Customization)。相较于传统的微调方法,PuLID无需复杂的参数优化就可以实现高效的身份ID定制,且能最大程度减少对原始模型行为的干扰。 PuLID是通过将轻量级的…...
SpringBoot启动流程分析之创建SpringApplication对象(一)
SpringBoot启动流程分析之创建SpringApplication对象(一) 目录: 文章目录 SpringBoot启动流程分析之创建SpringApplication对象(一)1、SpringApplication的构造方法1.1、推断应用程序类型1.2、设置Initializers1.3、设置Listener1.4、推断main方法所在类 流程分析…...
SSH简介 特点以及作用
引言 SSH(Secure Shell)是一种用于安全远程访问和数据传输的网络协议。它提供了一种安全的机制,使得用户可以在不安全的网络中安全地进行远程登录、命令执行和文件传输。SSH通过加密技术和认证机制来保护数据的安全性,防止数据在…...
MQTT服务搭建及python使用示例
1、MQTT协议 1.1、MQTT介绍 MQTT(Message Queuing Telemetry Transport)是一种轻量级的、基于发布/订阅模式的通信协议,通常用于物联网设备之间的通讯。它具有低带宽、低功耗和开放性等特点,适合在网络带宽有限或者网络连接不稳定…...
Ubuntu如何设置中文输入法
概述 Ubuntu 是一个基于 Debian 构建的开源操作系统,拥有广泛的用户群体和强大的社区支持。是免费、开源的操作系统。被设计为一个适用于个人电脑、服务器和云平台的通用操作系统。Ubuntu的目标是提供一个稳定、易于使用和免费的操作系统,以促进人们在计…...
PostgreSQL的pg_dump和 pg_dumpall 异同点
PostgreSQL的pg_dump和 pg_dumpall 异同点 基础信息 OS版本:Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本:16.2 pg软件目录:/home/pg16/soft pg数据目录:/home/pg16/data 端口:5777pg_dump 和 pg_dum…...
【Ping】Windows 网络延迟测试 ping 、telnet、tcping 工具
ping 命令 属于网络层的ICMP协议,只能检查 IP 的连通性或网络连接速度, 无法检测IP的端口状态。 telnet telnet命令,属于应用层的协议,用于远程登录,也可用于检测IP的端口状态。但是功能有限,只能检测一时…...
DuDuTalk:4G桌面拾音设备在银行网点服务场景的应用价值
随着科技的飞速发展,银行业也在不断地寻求创新以提高服务质量和效率。在这个过程中,4G桌面拾音设备作为一种新型的智能设备,其在银行网点服务场景中的应用价值逐渐凸显出来。本文将从多个角度探讨4G桌面拾音设备在银行网点服务场景的应用价值…...
QT 设置窗口不透明度
在窗口作为子窗口时,setWindowOpacity设置窗口的不透明度可能会失效。 QGraphicsOpacityEffect *opacityEffect new QGraphicsOpacityEffect(this); opacityEffect->setOpacity(1.0); this->setGraphicsEffect(opacityEffect);// 创建属性动画对象ÿ…...
如何在Python中实现文本相似度比较?
在Python中实现文本相似度比较可以通过多种方法,每种方法都有其适用场景和优缺点。以下是一些常见的文本相似度比较方法: 1. 余弦相似度(Cosine Similarity) 余弦相似度是通过计算两个向量之间夹角的余弦值来确定它们之间的相似…...
韩顺平0基础学Java——第7天
p110-p154 控制结构(第四章) 多分支 if-elseif-else import java.util.Scanner; public class day7{public static void main(String[] args) {Scanner myscanner new Scanner(System.in);System.out.println("input your score?");int s…...
性能远超GPT-4!谷歌发布Med-Gemini医疗模型;李飞飞首次创业瞄准空间智能;疫苗巨头联合OpenAl助力AI医疗...
AI for Science 企业动态速览—— * 谷歌 Med-Gemini 医疗 AI 模型性能远超 GPT-4 * 斯坦福李飞飞首次创业瞄准「空间智能」 * 疫苗巨头 Moderna 与 OpenAl 达成合作 * 美国能源部推动 AI 在清洁能源领域的应用 * 美年健康荣获「2024福布斯中国人工智能创新场景应用企业TOP10」…...
中国科技大航海时代,“掘金”一带一路
文|白 鸽 编|王一粟 “这不就是90年代的内地吗?” 在深度考察完沙特市场后,华盛集团联合创始人兼CEO张霆对镜相工作室感慨道。 在张霆看来,沙特落后的基建(意味着大量创新空间)、刚刚开放…...
ffmpeg7.0 flv支持hdr
ffmpeg7.0 flv支持hdr 自从ffmpeg6.0应用enhance rtmp支持h265/av1的flv格式后,7.0迎来了flv的hdr能力。本文介绍ffmpeg7.0如何支持hdr in flv。 如果对enhance rtmp如何支持h265不了解,推荐详解Enhanced-RTMP支持H.265 1. enhance rtmp关于hdr 文档…...
【教程】极简Python接入免费语音识别API
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,请不吝给个[点赞、收藏、关注]哦~ 安装库: pip install SpeechRecognition 使用方法: import speech_recognition as srr sr.Recognizer() harvard sr…...
详解typora配置亚马逊云科技Amazon S3图床
欢迎免费试用亚马逊云科技产品:https://mic.anruicloud.com/url/1333 当前有很多不同的博客社区,不同的博客社区使用的编辑器也不尽相同,大概可以分为两种,一种是markdown格式,另外一种是富文本格式。例如华为云开发者…...
Python sqlite3库 实现 数据库基础及应用 输入地点,可输出该地点的爱国主义教育基地名称和批次的查询结果。
目录 【第11次课】实验十数据库基础及应用1-查询 要求: 提示: 运行结果: 【第11次课】实验十数据库基础及应用1-查询 声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 1.简答题 数据库文件Edu_Base.db&#…...
iOS-SSL固定证书
文章目录 1. SSL简介2. 证书锁定原理1.1 证书锁定1.2 公钥锁定1.3 客户端获取公钥1.4 客户端使用SSL锁定选择1.5 项目支持SSL证书锁定1.6 问题记录1. SSL简介 证书锁定(SSL/TLS Pinning)顾名思义,将服务器提供的SSL/TLS证书内置到移动端开发的APP客户端中,当客户端发起请求…...
docker 开启 tcp 端口
前言:查了很多网上资料 都说要修改daemons,json 完全不管用,而且还导致添加 {“host”:["tcp://0.0.0.0:2375","unix:///var/lib/docker.sock"]} 后,docker restart 失败,浪费了不少时间 !&am…...
zookeeper之分布式环境搭建
ZooKeeper的分布式环境搭建是一个涉及多个步骤的过程,主要包括准备工作、安装ZooKeeper、配置集群、启动服务以及验证集群状态。以下是搭建ZooKeeper分布式环境的基本步骤: 1. 准备工作 确保所有节点的系统时间同步。确保所有节点之间网络互通…...
java设计模式三
工厂模式是一种创建型设计模式,它提供了一个创建对象的接口,但允许子类决定实例化哪一个类。工厂模式有几种变体,包括简单工厂模式、工厂方法模式和抽象工厂模式。下面通过一个简化的案例和对Java标准库中使用工厂模式的源码分析来说明这一模…...
##12 深入了解正则化与超参数调优:提升神经网络性能的关键策略
文章目录 前言1. 正则化技术的重要性1.1 L1和L2正则化1.2 Dropout1.3 批量归一化 2. 超参数调优技术2.1 网格搜索2.2 随机搜索2.3 贝叶斯优化 3. 实践案例3.1 设置实验3.2 训练和测试 4. 结论 前言 在深度学习中,构建一个高性能的模型不仅需要一个好的架构…...
TODESK怎么查看有人在远程访问
odesk怎么查看有人在远程访问 Todesk作为一款远程桌面控制软件,为用户提供了便捷的远程访问与控制功能。但在享受这种便利的同时,许多用户也关心如何确保自己设备的安全,特别是如何知道是否有人在未经授权的情况下远程访问自己的电脑。本文将…...
【Web漏洞指南】服务器端 XSS(动态 PDF)
【Web漏洞指南】服务器端 XSS(动态 PDF) 概述流行的 PDF 生成工具常见攻击载荷 概述 如果一个网页使用用户控制的输入创建 PDF,您可以尝试欺骗创建 PDF 的机器人以执行任意的 JS 代码。 因此,如果PDF 创建机器人发现某种HTML标签…...
Qt中的对象树
一. QT对象树的概念 QObject 的构造函数中会传入一个 Parent 父对象指针,children() 函数返回 QObjectList。即每一个 QObject 对象有且仅有一个父对象,但可以有很多个子对象。 那么Qt这样设计的好处是什么呢?很简单,就是为了方…...
QT-day1
1、 自由发挥应用场景,实现登录界面。 要求:尽量每行代码都有注释。 #ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> #include <QIcon>//窗口 #include <QLabel>//标签库 #include <QMovie>//动态图片库 #include…...
安装oh-my-zsh(命令行工具)
文章目录 一、安装zsh、git、wget二、安装运行脚本1、curl/wget下载2、手动下载 三、切换主题1、编辑配置文件2、切换主题 四、安装插件1、zsh-syntax-highlighting(高亮语法错误)2、zsh-autosuggestions(自动补全) 五、更多优化配…...
试用网站建设/电子商务seo名词解释
作者简介 青花瓷的平方,携程技术专家,主要从事无线开发,负责携程支付iOS相关开发工作。一、引言Combine.framework 是Apple在2019 WWDC 上基于Swift推出的函数响应框架(Functional Reactive Programming),支持Apple全平…...
查飞机进出港的app/网站seo外包公司
背景: 我们有个车管系统,需要定期的去查询车辆的违章,之前一直是调第三方接口去查,后面发现数据不准确(和深圳交警查的对不上),问题比较多。于是想干脆直接从深圳交警上查,那不就不会…...
移动论坛网站模板/百度广告电话号码是多少
引言LabVIEW是一种简单易学、形象直观的图形化编程语言,也称为G语言,具有丰富的同传统仪器外观类似的控件库(如旋钮、仪表盘、温度计、波形图表等),可以构建漂亮专业的用户界面,同时,内部提供了庞大的函数库(如数据采集…...
自己的网站 做采集怎么做/百度推广在线客服
2019独角兽企业重金招聘Python工程师标准>>> 优先队列 出队顺序与入队顺序无关, 和优先级有关 对于总共N个请求,使用普通数组或顺序数组, 最差N^2, 使用堆:NLogN 二叉堆 孩子节点不大于它的父亲节点(最大堆…...
磁力搜索网站怎么做的/优化师
摘要:本文根据 DTCC 数据库大会分享内容整理而成,将介绍工行 IT 架构转型中传统 OLTP 数据库架构面临的挑战和诉求,构建基于 MySQL 分布式企业级解决方案实践历程,包括技术选择、高可用设计、两地三中心容灾、运维管理、资源使用效…...
一 网站建设的目的和目标/软文范例大全1000字
转:http://www.myexception.cn/javascript/871757.html 什么是 JavaScript?你该如何执行它 什么是 JavaScript?你该如何执行它? JavaScript 是一种基于文本的程序设计语言,在被执行之前不需要进行任何转换。其它程…...