前端实现websocket类封装

随着Web应用程序的发展,越来越多的人开始利用Websocket技术来构建实时应用程序。Websocket是一种在客户端和服务器之间建立持久连接的协议。这种协议可以在一个单独的连接上实现双向通信。与HTTP请求-响应模型不同,Websocket允许服务器自主地向客户端发送数据。这种实时连接的能力使得Websocket在许多应用场景中得到了广泛的应用。

Websocket技术的优点之一是减少了网络延迟。在传统的HTTP请求-响应模型中,客户端必须不断地向服务器发送请求以获取更新的数据。这种不断的请求-响应循环会占用大量的带宽和处理能力。而Websocket的持久连接可以在服务器有新数据时立即向客户端发送,从而减少了网络延迟和服务器负载。

另一个优点是Websocket可以处理大量的并发连接。在传统的HTTP请求-响应模型中,每个请求都必须在服务器上进行处理,这可能会对服务器造成负载压力。但是,Websocket的持久连接可以在服务器上保持打开状态,从而减少了与每个连接相关的开销。这使得服务器可以处理大量的并发连接而不会降低性能。

Websocket还可以用于实时通信。例如,聊天应用程序可以使用Websocket来实现实时消息传递。在这种情况下,Websocket的持久连接可以在服务器上保持打开状态,以便客户端可以接收实时消息。这种实时通信的能力使得Websocket在许多应用程序中得到了广泛的应用。

总之,Websocket技术在现代Web应用程序中发挥着越来越重要的作用。它可以减少网络延迟和服务器负载,处理大量的并发连接,并提供实时通信能力。因此,如果您正在构建一个需要实时更新的Web应用程序,那么Websocket技术可能是您的理想选择。

封装类实现

import { WebSocketConfigOption } from './WebSocketConfigOption';export class ReconnectableWebSocket {private ws!: WebSocket; // ws实例private opt: WebSocketConfigOption; // ws配置项private lockReconnect: boolean = false; // 避免ws重复连接private isClosingWindow: boolean = false;private reconnectTimeout: any;private heartSendInterval: any;constructor(option: WebSocketConfigOption) {if (null === option.url || '' === option.url) {throw ('url不能为空');}this.opt = option;this.initWebSocket();}private initWebSocket() {if (null == this.opt.secWebSocketProtocol) {this.ws = new WebSocket(this.opt.url);} else if (this.opt.secWebSocketProtocol.length == 0) {this.ws = new WebSocket(this.opt.url);} else {this.ws = new WebSocket(this.opt.url, this.opt.secWebSocketProtocol);}this.initEventHandle();window.onbeforeunload = () => {this.isClosingWindow = true;this.ws.close(); // 当窗口关闭时,主动去关闭websocket连接。}}private initEventHandle() {this.ws.onclose = () => {console.log('ws连接关闭!' + this.opt.url);this.opt.onclose && this.opt.onclose();this.heartCheckStop();if (!this.isClosingWindow) {this.reconnect();}}this.ws.onerror = () => {console.log('ws连接错误!' + this.opt.url);this.opt.onerror && this.opt.onerror();this.heartCheckStop();if (!this.isClosingWindow) {this.reconnect();}}this.ws.onopen = () => {console.log('ws连接成功!' + this.opt.url);this.opt.onopen && this.opt.onopen();this.heartCheckStart();}this.ws.onmessage = (event: any) => {this.opt.onmessage && this.opt.onmessage(event);}}/** 重连 */private reconnect() {if (this.lockReconnect) {return;}this.lockReconnect = true;this.reconnectTimeout = setTimeout(() => {this.initWebSocket();this.lockReconnect = false;}, 2000);}/** 关闭重连 */private reconnectStop(): void {clearTimeout(this.reconnectTimeout);}/** 开启心跳包保持连接 */private heartCheckStart(): void {this.ws.send('heartCheck');this.heartSendInterval = setInterval(() => {this.ws.send('heartCheck');}, 5 * 60 * 1000);}/** 关闭心跳包 */private heartCheckStop(): void {clearInterval(this.heartSendInterval);}/** 主动关闭连接 */public close(): void {this.reconnectStop();this.heartCheckStop();this.isClosingWindow = true;this.ws.close();}}

配置类实现

export type WebSocketConfigOption = {url: string;secWebSocketProtocol?: Array<string>;onopen?: () => void;onmessage?: (msg: any) => void;onerror?: () => void;onclose?: () => void;}

应用示例

import { WebSocketConfigOption } from '../websocket/WebSocketConfigOption';
import { ReconnectableWebSocket } from '../websocket/ReconnectableWebSocket';
import { InnerMqService } from '../../rx/inner-mq.service';export class MapMessageConnection {private ws!: ReconnectableWebSocket;constructor(private path: string,private innerMqService: InnerMqService,) {this.connection();}/** 连接 */private connection(): void {let wsConfig: WebSocketConfigOption = {url: this.path,onopen: () => {},onerror: () => {},onmessage: (msg: any) => {if (msg.data && msg.data !== '') {let data = JSON.parse(msg.data);this.innerMqService.pub(data.title, data.content);}}}this.ws = new ReconnectableWebSocket(wsConfig);}/** 断开连接 */public disConnection(): void {this.ws.close();}}
import { InnerMqClient } from '../../rx/inner-mq.service';
import { SubmitService } from '../../service/submit.service';
import { MapBase } from '../../map/map-base';
import { CommonUtil } from '../../util/common-util';
import { MapPage } from '../../view/page/map/map.page';
import { MapDraw } from '../../map/draw/map-draw';
import { MapWrap } from '../../map/draw/map-wrap';
import { GeoUtil } from "../../map/geo-util";
import { Point } from "../../map/entity/Point";export class MapMessageProcessor {constructor(private mqClient: InnerMqClient,private submitService: SubmitService,private mapBase: MapBase,private mapPage: MapPage,) {/** 放大 */mqClient.sub('ZoomIn').subscribe((res) => {mapBase.zoomIn();});/** 缩小 */mqClient.sub('ZoomOut').subscribe((res) => {mapBase.zoomOut();});/** 拖动 */mqClient.sub('Pan').subscribe((res) => {mapBase.pan();});/** 显示网格 */mqClient.sub('GridSwitch').subscribe((res) => {let update;if (mapBase.getGridVisible()) {mapBase.closeGrid();update = false;} else {mapBase.showGrid();update = true;}let config = mapBase.getMapConfig();if (config) {config.grid = update;CommonUtil.setConfigCache(config);mapBase.setMapConfig(config);}});/** 切换图层源 */mqClient.sub('SwitchResource').subscribe((res) => {// 切换图层debuggerlet lastType = mapBase.getCurrentCoordinateType();mapBase.switchMapResource(res);let currentType = mapBase.getCurrentCoordinateType();// 保存设置let config = mapBase.getMapConfig();if (config) {config.layer = res;CommonUtil.setConfigCache(config);mapBase.setMapConfig(config);}// 检查坐标类型if (lastType != currentType) {if (lastType == 'wgs84' && currentType == 'gcj02') {mapBase.turnMapFeaturesFromWgs84ToGcj02();} else if (lastType == 'gcj02' && currentType == 'wgs84') {mapBase.turnMapFeaturesFromGcj02ToWgs84();}}// 回调setTimeout(() => {mapPage.updateShowInfo();});});/** 绘制类型切换 - */mqClient.sub('SwitchDrawType').subscribe((res) => {mapBase.setDrawType(res);});/** 绘制 - */mqClient.sub('OpenDraw').subscribe((res) => {mapBase.pan();mapBase.removeDrawedFeatures();mapBase.openDraw({drawEnd: () => {setTimeout(() => {mapBase.removeDrawInteraction();})},modifyEnd: () => {}});});/** 绘制指定多边形并定位 - */mqClient.sub('DrawPolygonAndPositioning').subscribe((res) => {mapBase.pan();mapBase.removeDrawedFeatures();let blocks = JSON.parse(res);for (let i = 0; i < blocks.length; i++) {let points: Array<Point> = [];for (let j = 0; j < blocks[i].length; j++) {let point = new Point(blocks[i][j].lng, blocks[i][j].lat);if (mapBase.getCurrentCoordinateType() == 'wgs84') {points.push(GeoUtil.gcj02_To_wgs84(point));} else {points.push(point);}}let feature = MapDraw.createPolygonFeature(points);MapWrap.addFeature(mapBase, mapBase.drawLayerName, feature);}mapBase.setFitviewFromDrawLayer();});/** fitview - */mqClient.sub('Fitview').subscribe((res) => {mapBase.setFitviewFromDrawLayer();});/** 删除绘制 - */mqClient.sub('RemoveDrawedShape').subscribe((res) => {mapBase.removeDrawedFeatures();});/** 提交区块下载 - */mqClient.sub('SubmitBlockDownload').subscribe((res) => {let data = {tileName: this.mapBase?.getCurrentXyzName(),mapType: CommonUtil.getMapType(this.mapBase?.getCurrentXyzName()),tileUrl: this.mapBase?.getCurrentXyzUrlResources(),points: this.mapBase?.getDrawedPoints(),};this.submitService.blockDownload(data).then((r) => {});});/** 提交世界下载 - */mqClient.sub('SubmitWorldDownload').subscribe((res) => {let data = {tileName: this.mapBase?.getCurrentXyzName(),mapType: CommonUtil.getMapType(this.mapBase?.getCurrentXyzName()),tileUrl: this.mapBase?.getCurrentXyzUrlResources()};this.submitService.worldDownload(data).then((r) => {});});}}

如果对您有帮助

感谢支持技术分享,请点赞支持:

技术合作交流qq:2401315930

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

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

相关文章

想要学会JVM调优,先掌握JVM内存模型和JVM运行原理

1、前言 今天将和你一起探讨Java虚拟机&#xff08;JVM&#xff09;的性能调优。 JVM算是面试中的高频问题了&#xff0c;通常情况下总会有人问到&#xff1a;请你讲解下 JVM 的内存模型&#xff0c;JVM 的 性能调优做过&#xff1f; 2、为什么 JVM 在 Java 中如此重要 首…

ansible加密

本章主要介绍如何对ansible中的playbook 进行加密。 对整个playbook进行加密查看加密文件运行加密的playbook对playbook进行解密使用密码文件对单个字符串进行加密 前面写了许多playbook&#xff0c;这些playbook都是以明文的方式存在的&#xff0c;有时想对这些 playbook进…

利用网络教育系统构建个性化学习平台

在现代教育中&#xff0c;网络教育系统作为一种创新的学习方式&#xff0c;为学生提供了更加个性化和灵活的学习体验。在本文中&#xff0c;我们将通过简单的技术代码&#xff0c;演示如何构建一个基础的网络教育系统&#xff0c;为学生提供个性化的学习路径和资源。 1. 环境…

在Go语言中实现HTTP请求的缓存

大家好&#xff0c;我是你们可爱的编程小助手&#xff0c;今天我们要一起探讨如何使用Go语言实现HTTP请求的缓存。听起来是不是很酷&#xff1f;让我们开始吧&#xff01; 首先&#xff0c;我们要明白什么是缓存。简单来说&#xff0c;缓存就是将数据存储在内存中&#xff0c;…

从 WasmEdge 运行环境读写 Rust Wasm 应用的时序数据

WebAssembly (Wasm) 正在成为一个广受欢迎的编译目标&#xff0c;帮助开发者构建可迁移平台的应用。最近 Greptime 和 WasmEdge 协作&#xff0c;支持了在 WasmEdge 平台上的 Wasm 应用通过 MySQL 协议读写 GreptimeDB 中的时序数据。 什么是 WebAssembly WebAssembly 是一种…

Mysql中 distinct 和 group by 哪个效率高?

结论 先说结论 有索引的情况下&#xff1a;group by和distinct都能使用索引&#xff0c;效率相同 无索引的情况下&#xff1a;distinct效率高于group by。原因是distinct 和 group by都会进行分组操作&#xff0c;但group by可能会进行排序&#xff0c;触发filesort&#xff…

DevC++ easyx 从图片放缩理解双线性插值意义

很久就想实现的一个功能&#xff0c;图片能够拖动&#xff0c;图片能够通过视口局部显示&#xff0c;但是图片放大缩小还是解决。 于是心心念念半年过去了。 恰逢校园地图大作业&#xff0c;按意思来说是可视化&#xff0c;想着能不能改改代码&#xff0c;搓一个地图&#xf…

Flutter配置Android和IOS允许http访问

默认情况下&#xff0c;Android和IOS只支持对https的访问&#xff0c;如果需要访问不安全的连接&#xff0c;也就是http&#xff0c;需要做以下配置。 Android 在res目录下的xml目录中(如果不存在&#xff0c;先创建xml目录)&#xff0c;创建一个xml文件network_security_con…

Appium+python自动化(三)- SDK Manager(超详解)

简介 本来宏哥一开始打算用真机做的&#xff0c;所以在前边搭建环境时候就没有下载SDK&#xff0c;但是由于许多小伙伴通过博客发短消息给宏哥留言说是没有真机&#xff0c;所以顺应民意整理一下模拟器&#xff0c;毕竟“得民心者&#xff0c;得天下”。SDK顾名思义&#xff0c…

【Linux学习笔记】Linux下nginx环境搭建

1、下载nginx 安装rpm命令: rpm ivh nginx-release.rpm。(直接使用linux命令下载wget http://nginx.org/packages/rhel/6/noarch/RPMS/nginx-release-rhel-6-0.el6.ngx.noarch.rpm 2、设置nginx开机启动 chkconfig nginx on 3、开启nginx服务 方法一&#xff1a;service nginx…

引力魔方的基础知识总结

1.简介&#xff1a;引力魔方是投放推荐广告的渠道&#xff0c;融合了钻展和超推&#xff1b;更新升级平台之后统一叫做人群精准推广&#xff1b; 2.展位&#xff1a;包括淘宝首页、内页频道页、门户、帮派、画报等多个淘宝站内广告位 &#xff0c;每天拥有超过8亿的展现量&…

统一身份认证,构建数字时代的安全壁垒——统一身份认证介绍、原理和实现方法

前言 随着数字化时代的来临&#xff0c;个人和机构在互联网上的活动越来越频繁&#xff0c;对于身份认证的需求也愈发迫切。为了有效应对身份欺诈、数据泄露等问题&#xff0c;统一身份认证&#xff08;Unified Identity Authentication&#xff09;应运而生。 在本文博主将介…

快速排序:高效分割与递归,排序领域的王者算法

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《数据结构&算法》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! &#x1f4cb; 前言 快速排序这个名词&#xff0c;快排之所以叫快排肯定是有点东西的。他在处理大规模数据集时表现及其…

MySQL数据库编译及安装

将安装mysql 所需软件包传到/opt目录下 cd /opt mysql-5.7.20.tar.gz boost_1_59_0.tar.gz #支持c的运行库 安装环境依赖包 yum -y install \ gcc \ gcc-c \ ncurses \ #字符终端下图形互动功能的动态库 ncurses-devel \ #ncurses开发包 bison \ #语法分析器 cmake #mysql需…

怎么设置Facebook双重验证,让Facebook账号更稳定?

对于跨境电商而言&#xff0c;Facebook 账号被封是常有的事&#xff0c;原因之一可能是没有给 Facebook 设置双重验证&#xff0c;今天就和大家科普一下什么是 Facebook双重验证以及如何设置&#xff0c;另外&#xff0c;作为跨境卖家&#xff0c;我们还需要了解如何保护 Faceb…

Bert-vits2最终版Bert-vits2-2.3云端训练和推理(Colab免费GPU算力平台)

对于深度学习初学者来说&#xff0c;JupyterNoteBook的脚本运行形式显然更加友好&#xff0c;依托Python语言的跨平台特性&#xff0c;JupyterNoteBook既可以在本地线下环境运行&#xff0c;也可以在线上服务器上运行。GoogleColab作为免费GPU算力平台的执牛耳者&#xff0c;更…

视频格式网络地址转换视频到本地,获取封面、时长,其他格式转换成mp4

使用ffmpeg软件转换网络视频&#xff0c;先从官网下载对应操作系统环境的包 注意:网络地址需要是视频格式结尾&#xff0c;例如.mp4,.flv 等 官网地址&#xff1a;Download FFmpeg window包&#xff1a; linux包&#xff1a; 如果下载缓慢&#xff0c;下载迅雷安装使用…

Pycharm2023版本:Python远程调试配置详解

工欲善其事&#xff0c;必先利其器 首先你需要选择一个专业版本的pycharm&#xff0c;社区版本不支持远程配置功能&#xff0c;专业版下载地址&#xff1a;Pycharm 2023 双击程序进行安装&#xff0c;30天内免费试用&#xff0c;如果想要永久使用&#xff0c;办法你懂的&…

GBASE南大通用 GCDW阿里云计算巢:自动化部署云原生数据仓库

目前&#xff0c;GBASE南大通用已与阿里云计算巢合作&#xff0c;双方融合各自技术优势&#xff0c;助力企业用户实现云上数据仓库的自动化部署&#xff0c;让用户在云端获取数据仓库服务“更简单”&#xff0c;让用户在云端使用数据仓库服务“更便捷”&#xff0c;满足企业用户…

Arm CCA机密计算扩展

目录 Realms Realm World和Root World Arm TrustZone扩展和Arm RME之间有什么区别? 在《什么是机密计算?》中所述,Arm CCA允许您在阻止更高特权软件实体(例如Hypervisor)访问的同时部署应用程序或虚拟机(VM)。然而,通常由这些特权软件实体管理内存等资源。在这种情况…