当前位置: 首页 > news >正文

封装websocket

摘要

本文将介绍两种不同的WebSocket客户端封装方法:使用函数封装和使用类封装。我们将分析它们的实现方式、特点和适用场景,以及如何根据项目需求选择合适的封装方式。

1. 引言

WebSocket提供了全双工通信渠道,允许服务器主动发送信息给客户端。在实际开发中,封装WebSocket客户端可以简化开发流程,提高代码的可维护性和可复用性。

2. 函数封装:createWebSocket

createWebSocket函数是一种简单的封装方式,它通过接收必要的参数来创建和管理WebSocket连接。以下是其主要特点:

  • 简洁性:作为一个函数,它提供了一种快速且直接的方式来处理WebSocket连接。
  • 自动重连:实现了自动重连机制,能够在连接断开时尝试重新连接。
  • 心跳检测:通过定时发送心跳包来保持连接的活跃状态。
  • 灵活性:提供了发送消息和关闭连接的方法,使得调用者可以灵活地控制WebSocket的生命周期。

3. 类封装:WebSocketClient

WebSocketClient类提供了面向对象的方式来管理WebSocket连接,具有以下特性:

  • 封装性:将WebSocket的创建、管理和销毁封装在一个类中,提高了代码的模块化。
  • 状态管理:通过属性来管理WebSocket的状态,如是否在重连中、是否手动关闭等。
  • 错误处理:拥有错误消息队列,能够在连接失败时缓存消息,并在重连成功后发送。
  • 事件监听:定义了多种事件处理方法,如onopenonerroroncloseonmessage,使得状态变化更加可控。

export function createWebSocket(url, onOpen, onMessage) {if (!url) return;let canReconnect = true;// 避免重复连接let lockReconnect = false;let needReconnect = true;let ws = null;connect();heartCheck();// 连接服务端function connect() {ws = new WebSocket(url);ws.onopen = function () {if (onOpen) {onOpen();}};ws.onmessage = function (msg) {if (msg && msg.data) {let response = JSON.parse(msg.data);//console.log(response);if (onMessage) {onMessage(response);} else {canReconnect = false;}}};ws.onerror = function () {console.log("链接错误");reconnect();};ws.onclose = function () {console.log("close");if (!needReconnect) {ws.close();} else {reconnect();}};}// 重新连接服务端function reconnect() {if (!canReconnect || lockReconnect) {return;}console.log("reconnect", "reconnect");lockReconnect = true;setTimeout(function () {connect();lockReconnect = false;}, 5000);}// 保持心跳连接function heartCheck() {if (ws && ws.readyState === 1) {ws.send(JSON.stringify({id: new Date().getTime(),method: "PING",}));}setTimeout(function () {heartCheck();}, 15000);}// 发送websocket消息function sendMessage(message) {if (ws && ws.readyState === 1) {ws.send(message);} else {console.log("WebSocket is not open");}}// 关闭websocket连接function closeWs() {needReconnect = false;ws.close();}return {ws,sendMessage,closeWs,};
}

class WebSocketClient {// 要连接的URLurl// 一个协议字符串或一个协议字符串数组。// 这些字符串用来指定子协议,这样一个服务器就可以实现多个WebSocket子协议protocols// WebSocket 实例ws// 是否在重连中isReconnectionLoading = false// 延时重连的 idtimeId = null// 是否是用户手动关闭连接isCustomClose = false// 错误消息队列errorStack = []constructor(url, protocols) {this.url = url;this.protocols = protocols;this.ws = null;this.onOpen = null;this.onMessage = null;this.connect();}connect() {if ("WebSocket" in window) {// 实例化this.ws = new WebSocket(this.url, this.protocols);// 监听事件this.onopen();this.onerror();this.onclose();} else {console.log("你的浏览器不支持 WebSocket");}}// 监听成功onopen() {this.ws.onopen = () => {console.log(this.ws, "onopen");// 发送成功连接之前所发送失败的消息this.errorStack.forEach((message) => {this.send(message);});this.errorStack = [];this.isReconnectionLoading = false;};}// 监听错误onerror() {this.ws.onerror = (err) => {console.log(err, "onerror");this.reconnection();this.isReconnectionLoading = false;};}// 监听关闭onclose() {this.ws.onclose = () => {console.log("onclose");// 用户手动关闭的不重连if (this.isCustomClose) return;this.reconnection();this.isReconnectionLoading = false;};}// 接收 WebSocket 消息async onmessage(fn) {this.ws.onmessage = (event) => {try {const data = JSON.parse(event.data)fn(data )} catch (error) {console.log(error, 'error')}}}// 重连reconnection() {// 防止重复if (this.isReconnectionLoading) returnthis.isReconnectionLoading = trueclearTimeout(this.timeId)this.timeId = setTimeout(() => {this.createWs()}, 3000)}// 发送消息send(message) {// 连接失败时的处理if (this.ws.readyState !== 1) {
//没有发送成功的信息保存下来,链接成功后重新发送this.errorStack.push(message)return}this.ws.send(message)}// 手动关闭close() {this.isCustomClose = truethis.ws.close()}// 手动开启start() {this.isCustomClose = falsethis.reconnection()}// 销毁destroy() {this.close()this.ws = nullthis.errorStack = nullthis.eventCenter = null}}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 代码随想录算法训练营day50 | 深度优先搜索理论基础、98. 所有可达路径、广度优先搜索理论基础
  • 教程:使用Python裁剪TIF影像为多个自定义大小的小块(分割栅格)
  • K8S 探针
  • 创建、使用、删除 数据库
  • web的发展历史,互联网和万维网的关系
  • QT自定义信号槽
  • python 压力测试脚本
  • 主要内容和创新点、研究方法和实现途径这两个概念在学术研究和技术开发中各有侧重点
  • Matplotlib基本操作
  • kubernetes的pod基础
  • MySQL 数据库管理
  • 微信小程序——弹出隐私指引教程(含代码)
  • C:每日一练:单身狗(2.0版本)
  • 【JAVA CORE_API】Day18 网络编程、线程、在线聊天室v1.0
  • 单片机存储芯片 W25QXX、AT24C02
  • JavaScript-如何实现克隆(clone)函数
  • 10个确保微服务与容器安全的最佳实践
  • 2017-09-12 前端日报
  • CODING 缺陷管理功能正式开始公测
  • JAVA多线程机制解析-volatilesynchronized
  • python_bomb----数据类型总结
  • spring-boot List转Page
  • SpriteKit 技巧之添加背景图片
  • Transformer-XL: Unleashing the Potential of Attention Models
  • Vue.js源码(2):初探List Rendering
  • 阿里云Kubernetes容器服务上体验Knative
  • 免费小说阅读小程序
  • 批量截取pdf文件
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 为什么要用IPython/Jupyter?
  • 异常机制详解
  • 字符串匹配基础上
  • 昨天1024程序员节,我故意写了个死循环~
  • ​如何在iOS手机上查看应用日志
  • ​探讨元宇宙和VR虚拟现实之间的区别​
  • #{} 和 ${}区别
  • #Linux(权限管理)
  • (¥1011)-(一千零一拾一元整)输出
  • (55)MOS管专题--->(10)MOS管的封装
  • (Oracle)SQL优化技巧(一):分页查询
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (备忘)Java Map 遍历
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (算法)硬币问题
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • (游戏设计草稿) 《外卖员模拟器》 (3D 科幻 角色扮演 开放世界 AI VR)
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • .axf 转化 .bin文件 的方法
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .Net CF下精确的计时器
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .Net core 6.0 升8.0