WebSocket封装

提示:记录工作中遇到的需求及解决办法

文章目录

  • 前言
  • 二、背景
  • 三、WebSocket
    • 3.1 什么是 WebSocket ?为什么使用他?
  • 四、封装 WebSocket
    • 4.1 Javascript 版本
    • 4.2 Typescript 版本
    • 4.3 如何使用?
  • 五、我的痛点如何处理


前言

本文将介绍 WebSocket 的封装,比如:心跳机制,重连和一些问题如何去处理


二、背景

之前,钱包相关的查询,我们是使用的轮询方案来做的,后来更新了一次需求,需要做一些实时数据统计的更新,然后顺带给钱包的余额也用长连接来做了,好,那么故事就开始了…

某天,

「老板:」 我钱怎么没了,但是我这里查账户还有。

「我的内心:」 恩?这玩意难道说… 后端没返?

和后端沟通以后,感觉是返回了的,被挤账号了?排查了一段时间以后,最终我将问题锁定在手机息屏的操作上。

因为我们是一个 「H5」 的项目,APP 是嵌套在 webview 中,所以不能操作原生的事件来处理,只能将方案控制在浏览器提供的事件来处理。

好了,接下来各位可以看我是如何处理这个问题,如果没有搞过也是可以有不少收获,也欢迎大神评论区交流其他方案。

三、WebSocket

3.1 什么是 WebSocket ?为什么使用他?

以下是百度百科中对 「WebSocket」 的定义:

WebSocket 是一种在单个 TCP 连接上进行 全双工 通信的协议。WebSocket 通信协议于2011年被 IETF 定为标准 RFC 6455,并由 RFC7936 补充规范。WebSocket API 也被 W3C 定为标准。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

「WebSocket 的关键特点」

  1. 「双向通信(Full Duplex)」
    • 客户端和服务器都可以主动发送数据,而不是像 HTTP 一样只能由客户端发起请求。
  2. 「实时性」
    • 消息可以实时传递,延迟更低,适合需要实时更新的场景。
  3. 「持久化连接」
    • 使用单个 TCP 连接完成多次数据交互,无需为每次通信重新建立连接。
  4. 「轻量级协议」
    • WebSocket 头部信息非常小,比传统 HTTP 请求的头部要轻量。
  5. 「节约资源」
    • 长连接减少了资源消耗,特别是在频繁通信的场景中。

上述中,是 AI 给我们总结的 WebSocket 的特点,接下来我们要知道我们为什么使用他,HTTP 他能不能做,他的局限性又在哪里?

「传统 HTTP 的局限性:」

  1. HTTP 是基于请求-响应模型的,客户端必须发起请求,服务器才能返回数据。
  2. 如果需要实时更新(如股票价格、在线聊天),通常需要使用轮询(Polling)或长轮询(Long Polling),这会导致:
    • 高资源消耗(频繁的连接建立和断开)。
    • 高网络流量(每次请求都包含冗长的 HTTP 头部信息)。
    • 更高的延迟(数据可能需要等待较长时间才能返回)。

其实 HTTP 是可以实现的,如果 HTTP 请求频繁三次握手和四次挥手的操作会占用大量资源,HTTP/1.1 以后开启了 「Keep-Alive (长连接)」,可以复用连接,但是实时的情况下,响应模型仍然会导致较高的延迟和资源消耗。

相比之下,WebSocket 通过一次握手建立连接以后,就可以保持双向通信,服务器可以主动推送数据,无需客户端轮询。解决了 HTTP 带来的一些痛点。

四、封装 WebSocket

我们将实现以下几个功能点:

  • 「重连」
  • 「心跳机制」
  • 「事件回调」
  • 「连接状态管理」
  • 「销毁」

4.1 Javascript 版本

class ReSocket {
   
  constructor(url, options = {
    }) {
   
    this.url = url; // WebSocket 服务器地址
    this.options = options; // 可选参数
    this.socket = null; // WebSocket 实例
    this.maxReconnectTimes = options.maxReconnectTimes || 5; // 最大重连次数
    this.reconnectTimes = 0; // 当前重连次数
    this.reconnectInterval = options.reconnectInterval || 3000; // 重连间隔时间(毫秒)
    this.isClosed = false; // 是否已关闭
    this.isOpen = false; // 是否已打开
    this.isConnect = false; // 是否已连接
    this.isReconnecting = false; // 是否正在重连
    this.isDestroyed = false; // 是否已销毁
    this.reconnectTimer = null; // 重连定时器
    this.heartbeatTimer = null; // 心跳定时器
    this.heartbeatInterval = options.heartbeatInterval || 30000; // 心跳间隔时间(默认30秒)
    this.heartbeatData = options.heartbeatData || "ping"; // 心跳数据
    this.onMessageCallback = null; // 消息接收回调
    this.onOpenCallback = null; // 连接成功回调
    this.onCloseCallback = null; // 连接关闭回调
  }


  
  // 创建WebSocket实例
  createSocket() {
   
    this.socket = new WebSocket(this.url);

    this.socket.onopen = () => {
   
      this.isOpen = true;
      this.isConnect = true;
      this.reconnectTimes = 0; // 重连次数归零
      this.startHeartbeat(); // 启动心跳机制
      if (this.onOpenCallback) this.onOpenCallback(); // 调用连接成功回调
    };

    this.socket.onmessage = event => {
   
      if (this.onMessageCallback) this.onMessageCallback(event.data); // 调用消息接收回调
    };

    this.socket.onclose = () => {
   
      this.isOpen = false;
      this.isConnect = false;
      this.stopHeartbeat(); // 停止心跳机制
      if (this.onCloseCallback) this.onCloseCallback(); // 调用连接关闭回调
      if (!this.isClosed && this.reconnectTimes < this.maxReconnectTimes) {
   
        this.reconnect(); // 尝试重连
      }
    };

    this.socket.onerror = error => {
   
      console.error("WebSocket 错误: ", error); // 错误处理
    };
  }

  // 开始连接
  connect

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Yolo11 基于DroneVehicle数据集的无人机视角下车辆目标检测

1、关于DroneVehicle数据集介绍 DroneVenicle数据集是由天津大学收集、标注的大型无人机航拍车辆数据集。 DroneVehicle 数据集由无人机采集的共 56,878 幅图像组成&#xff0c;其中一半为 RGB 图像&#xff0c;其余为红外图像。我们对五个类别进行了带有方向性边界框的丰富标…

Requests库01|使用Requests库发送 get/post/put/delete请求

学习目标&#xff1a; 能够使用Requests库发送 get/post/put/delete请求&#xff0c;获取响应状态码、数据能够使用UnitTest管理测试用例。 目录 一、Requests库安装和简介 二、设置http请求语法&#xff08;重要&#xff09; 三、应用案例&#xff08;重要&#xff09; …

[有用教程]从 Pixel 快速传输到 Android

概括 更换新手机很容易&#xff0c;但数据迁移却不容易。目前&#xff0c;用户喜欢转换品牌&#xff0c;应用市场上的转换工具也越来越多。然而&#xff0c;它们并不都是安全的。因此&#xff0c;选择一款简单、安全的迁移工具至关重要。 今天我们将讨论如何从 Pixel 转移到 …

【蓝桥杯研究生组】第15届Java试题答案整理

D 题 试题 D: 商品库存管理 时间限制: 3.0s 内存限制: 512.0MB 本题总分&#xff1a;10 分 【问题描述】 在库存管理系统中&#xff0c;跟踪和调节商品库存量是关键任务之一。小蓝经营的仓库中存有多种商品&#xff0c;这些商品根据类别和规格被有序地分类并编号&#xff0c;…

BUUCTF sqli-labs 1

这里就是单纯的找一下flag在哪&#xff0c;通关整个靶场在sql注入分区&#xff0c;虽然还没有通关。 这里要先看一下数据库都有哪些&#xff0c;用到语句&#xff1a;?id-1 union select 1,(select group_concat(schema_name) from information_schema.schemata),3-- 发现这个…

python实现自动登录12306抢票 -- selenium

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 python实现自动登录12306抢票 -- selenium 前言其实网上也出现了很多12306的代码&#xff0c;但是都不是最新的&#xff0c;我也是从网上找别人的帖子&#xff0c;看B站视频&…

Spring自动化创建脚本-解放繁琐的初始化配置!!!(自动化SSM整合)

一、实现功能(原创&#xff0c;转载请告知) 1.自动配置pom配置文件 2.自动识别数据库及数据表&#xff0c;创建Entity、Dao、Service、Controller等 3.自动创建database.properties、mybatis-config.xml等数据库文件 4.自动创建spring-dao.xml spring-mvc.xml …

[微服务] - MQ高级

在昨天的练习作业中&#xff0c;我们改造了余额支付功能&#xff0c;在支付成功后利用RabbitMQ通知交易服务&#xff0c;更新业务订单状态为已支付。 但是大家思考一下&#xff0c;如果这里MQ通知失败&#xff0c;支付服务中支付流水显示支付成功&#xff0c;而交易服务中的订单…

MySQL(面试题 - 同类型归纳面试题)

目录 一、MySQL 数据类型 1. 数据库存储日期格式时&#xff0c;如何考虑时区转换问题&#xff1f; 2. Blob和text有什么区别&#xff1f; 3. mysql里记录货币用什么字段类型比较好&#xff1f; 4. MySQL如何获取当前日期&#xff1f; 5. 你们数据库是否支持emoji表情存储…

aws(学习笔记第二十一课) 开发lambda应用程序

aws(学习笔记第二十一课) 开发lambda应用程序 学习内容&#xff1a; lambda的整体概念开发lambda应用程序 1. lambda的整体概念 借助AWS Lambda&#xff0c;无需预置或管理服务器即可运行代码。只需为使用的计算时间付费。借助 Lambda&#xff0c;可以为几乎任何类型的应用进…

【优选算法】查找总价格为目标值的两个商品

链接&#xff1a;LCR 179. 查找总价格为目标值的两个商品 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a;利用单调性&#xff0c;使用双指针算法解决问题 1.先从小到大排序 2. sum > t : right--; sum < t : left; sum t : return class Solution {public…

VUE echarts 教程二 折线堆叠图

VUE echarts 教程一 折线图 import * as echarts from echarts;var chartDom document.getElementById(main); var myChart echarts.init(chartDom); var option {title: {text: Stacked Line},tooltip: {trigger: axis},legend: {data: [Email, Union Ads, Video Ads, Dir…

bilibili 哔哩哔哩小游戏SDK接入

小游戏的文档 简介 bilibili小游戏bilibili小游戏具有便捷、轻量、免安装的特点。游戏包由云端托管&#xff0c;在哔哩哔哩APP内投放和运行&#xff0c;体验流畅&#xff0c;安全可靠。https://miniapp.bilibili.com/small-game-doc/guide/intro/ 没想过接入这个sdk比ios还难…

2024年中国新能源汽车用车发展怎么样 PaperGPT(二)

用车趋势深入分析 接上文&#xff0c;2024年中国新能源汽车用车发展怎么样 PaperGPT&#xff08;一&#xff09;-CSDN博客本文将继续深入探讨新能源汽车的用车强度、充电行为以及充电设施的现状。 用车强度 月均行驶里程&#xff1a;2024年纯电车辆月均行驶超过1500公里&…

自从学会Git,感觉打开了一扇新大门

“同事让我用 Git 提交代码&#xff0c;我居然直接把项目文件压缩发过去了……”相信很多初学者都经历过类似的窘境。而当你真正掌握 Git 时&#xff0c;才会发现它就像一本魔法书&#xff0c;轻松解决代码管理的种种难题。 为什么 Git 能成为程序员的标配工具&#xff1f;它究…

简易屏幕共享工具-基于WebSocket

前面写了两个简单的屏幕共享工具&#xff0c;不过那只是为了验证通过截屏的方式是否可行&#xff0c;因为通常手动截屏的频率很低&#xff0c;而对于视频来说它的帧率要求就很高了&#xff0c;至少要一秒30帧率左右。所以&#xff0c;经过实际的截屏工具验证&#xff0c;我了解…

yakit-靶场-高级前端加解密与验签实战(for嵌套纯享版)

高级前端加解密与验签实战 一、前端验证签名&#xff08;验签&#xff09;表单&#xff1a;HMAC-SHA256 使用hmac-sha256的十六进制key值可以加密 与页面加密后的值相同 热加载&#xff1a; encryptData func(p) { //sha256key值key codec.DecodeHex("313233343132333…

嵌入式入门Day35

网络编程 Day2 套接字socket基于TCP通信的流程服务器端客户端TCP通信API 基于UDP通信的流程服务器端客户端 作业 套接字socket socket套接字本质是一个特殊的文件&#xff0c;在原始的Linux中&#xff0c;它和管道&#xff0c;消息队列&#xff0c;共享内存&#xff0c;信号等…

模仿微信小程序wx.showModal自定义弹窗,内容可以修改

实现以下弹框样式功能 1.在components新建一个文件showModel.wpy作为组件&#xff0c;复制下面代码 <style lang"less" scoped> .bg_model {display: flex;justify-content: center;align-items: center;// 弹框背景.bg_hui {width: 100%;height: 100%;posi…

如何在 Ubuntu 22.04 上安装并开始使用 RabbitMQ

简介 消息代理是中间应用程序&#xff0c;在不同服务之间提供可靠和稳定的通信方面发挥着关键作用。它们可以将传入的请求存储在队列中&#xff0c;并逐个提供给接收服务。通过以这种方式解耦服务&#xff0c;你可以使其更具可扩展性和性能。 RabbitMQ 是一种流行的开源消息代…