前端实现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.hqwc.cn/news/305213.html

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

相关文章

【没有哪个港口是永远的停留~论文解读】Both Style and Fog Matter

Both Style and Fog Matter 原文&#xff1a;https://arxiv.org/pdf/2112.00484.pdf 解决问题&#xff1a;大雾、下雨、下雪天模糊场景 其他人做法&#xff1a; 1-去雾算法&#xff0c;人工干扰 2-合成的雾图像&#xff0c;不像真实的雾图像那样真实&#xff0c;也会扩大清…

Android中_Service生命周期和AMS流程的创建

Service生命周期可以结合Android生命周期分析。 Service生命周期可以从两种启动Service的模式开始讲起&#xff0c;分别是context.startService()和context.bindService()。 Service的生命周期与启动和绑定状态相关。当调用startService()方法启动服务时&#xff0c;会执行onS…

nginx报错upstream sent invalid header

nginx报错upstream sent invalid header 1.报错背景 最近由于nginx 1.20的某个漏洞需要升级到nginx1.25的版本。在测试环境升级完nginx后&#xff0c;发现应用直接报错502 bad gateway了。 然后查看nginx的errlog&#xff0c;发现&#xff1a; upstream sent invalid head…

java itext5 生成PDF并填充数据导出

java itext5 生成PDF并填充数据导出 依赖**文本勾选框****页眉**&#xff0c;**页脚****图片**实际图 主要功能有文本勾选框&#xff0c;页眉&#xff0c;页脚&#xff0c;图片等功能。肯定没有专业软件画的好看&#xff0c;只是一点儿方法。仅供参考。 依赖 <!--pdf-->&…

Google Ad帐号被封?代理IP和电子邮件可能是原因

海外广告投放工作中&#xff0c;账号是非常重要的环节。与在Facebook上运行广告相比&#xff0c;运行Google Ads在代理选择方面通常没有那么严格&#xff0c;因为 Google 对 IP 使用并不那么严格。但是&#xff0c;这并不意味着您可以不加考虑地使用任何代理IP。在本文中&#…

Vulnhub-Al-Web-1.0 靶机复现完整过程

一、信息收集 1.主机发现 arp-scan -l2.端口扫描 nmap -sV -p- 192.168.200.16PORTSTATESERVICEVERSIONMAC Address80/TCPOpenhttpApache httpd00:0C:29:C4:1B:78 (VMware) 3.目录扫描 python dirsearch.py -u http://192.168.200.16扫描出来这两个文件&#xff0c;首先先…

【算法刷题】Day25

文章目录 1. 粉刷房子题干&#xff1a;算法原理&#xff1a;1. 状态表示&#xff1a;2. 状态转移方程3. 初始化4. 填表顺序5. 返回值 代码&#xff1a; 2. 判定字符是否唯一题干&#xff1a;算法原理&#xff1a;1. 哈希表2. 位图思想 代码&#xff1a; 3. 丢失的数字题干&…

【Java系列】多线程案例学习——基于阻塞队列实现生产者消费者模型

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习JavaEE的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录…

百度飞桨文心生态成果最新披露:开发者达1070万 模型数超86万

前言 12月28日&#xff0c;由深度学习技术及应用国家工程研究中心主办的WAVE SUMMIT深度学习开发者大会2023在北京召开。百度首席技术官、深度学习技术及应用国家工程研究中心主任王海峰现场公布了飞桨文心五载十届最新生态成果&#xff0c;文心一言最新用户规模破1亿&#xf…

基于Docker的软件环境部署脚本,持续更新~

使用时CtrlF搜索你想要的环境&#xff0c;如果没有你想要的环境&#xff0c;可以评论留言&#xff0c;会尽力补充。 本文提供的部署脚本默认参数仅适合开发测试&#xff0c;请根据实际情况调节参数。 数据库 MySQL version: 3.9 services:mysql:image: mysql:8.0.35container…

win32 WM_MENUSELECT消息学习

之前写了一些win32的程序&#xff0c;处理菜单单击都是处理WM_COMMAND消息&#xff0c;通过 LOWORD(wParam) 获取菜单ID&#xff0c;判断单击的是哪个菜单项&#xff1b; 还有一些其他菜单消息&#xff1b; 当在菜单项中移动光标或鼠标&#xff0c;程序会收到许多WM_MENUSELEC…

JavaScript练习题第(四)部分

大家好关于JavaScript基础知识点已经发布&#xff1a;需要的大家可以去我的主要查看 &#xff08;当然了有任何不会的&#xff0c;可以私信我&#xff01;&#xff01;&#xff01;&#xff01;&#xff09; 为了巩固大家学习知识点给大家准备几道练习题&#xff1a; 当然&…