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

有效封装一个 WebSocket 供全局使用

前言

在现代 Web 应用中,实时通信已经成为越来越重要的一部分。而 WebSocket 技术的出现,使得实时通信变得更加高效和便捷。

WebSocket 协议是一种基于 TCP 协议的双向通信协议,它能够在客户端和服务器之间建立起持久性的连接,从而实现实时通信。

在前端开发中,为了更好地利用 WebSocket 技术,我们通常会对其进行封装,以便于全局调用并根据自己的业务做不同的预处理。

本文将介绍如何有效封装一个 WebSocket 供全局使用,并根据自己的业务做不同的预处理,实现更方便的调用,减少重复代码。

具体实现思想

我们将基于 Web API 提供的 WebSocket 类,封装一个 Socket 类,该类将提供以下功能:

  1. 建立 WebSocket 连接,并支持发送 query 参数。

  2. 发送、接收消息,支持对 WebSocket 的事件进行监听。

  3. 断开 WebSocket 连接。

  4. 支持心跳检测。

  5. 可以根据业务需要,对发送和接收的消息进行预处理。

接下来我们从实际使用的角度解释一下上面的代码,首先我们暴露了一个 useSocket 函数,该函数接收一个 options 配置项参数,支持的参数有:

  • url:要连接的 WebSocket URL;

  • protocols:一个协议字符串或者一个包含协议字符串的数组;

  • query:可以通过 URL 传递给后端的查询参数;

  • greet:心跳检测的打招呼信息;

  • customBase:自定义的 baseURL ,否则默认使用环境变量中定义的 env.VITE_APP_BASE_WS

在调用该函数后,我们首先会判断当前用户的浏览器是否支持 WebSocket,如果不支持给予用户提示。

然后我们实例化了一个 EventMap 类的实例对象 dep,你可以把它当作是一个依赖收集桶,当用户订阅了某个 WebSocket 事件时,我们将收集这个事件对应的回调作为依赖,在事件触发时,再通知该依赖,然后调用该事件对应的回调函数。

接下来我们定义了一个初始的重连次数记录值 reconnectCount 为 0,每当这个 WebSocket 重连时,该值会自增。

之后我们实例化了自己封装的 Socket 类,并传入了我们上面的三个参数。 在 Socket 类的构造函数 constructor 中,我们先取出配置项,把 query 内的参数拼接在 URL 上,然后使用 super 调用父类的构造函数进行建立 WebSocket 连接。

之后我们缓存了当前 Socket 实例化时的参数,再调用 initSocket() 方法去进行 WebSocket 事件的监听:

  • onopen:触发 dep 内 open 对应的回调函数并且打开心跳检测;

  • onclose:触发 dep 内 close 对应的回调函数并且对关闭的 code 码进行判断,如果是非正常关闭连接,将会进行重连,如果重连次数达到阈值,则通知给用户;

  • onerror:触发 dep 内 error 对应的回调函数;

  • onmessage:接收到服务端返回的数据,可以先根据自身业务做一些预处理,比如我就根据不同的数据类型进行了数据解析的预处理,之后再触发 dep 内 message 对应的回调函数并传入处理过后的数据。

我们也暴露了一些成员方法以供实例对象使用:

  • subscribe:订阅 WebSocket 事件,传入事件类型并须是 EventTypes 内的类型之一,第二个参数则是回调函数;

  • sendMessage`:同样的,我们在给服务端发送数据之前也可以根据自身业务做一些预处理,比如我将需要转成 JSON 的数据,在这里统一转换后再发送给服务端;

  • closeSocket:关闭 WebSocket 连接;

  • heartCheckStart:开始心跳检测,会创建一个定时器,在一定时间之后(默认是 55s)给服务端发送信息确认连接是否正常;

  • clearHeartCheck:清除心跳检测定时器(如果当前 WebSocket 连接已经关闭,则自动清除);

  • resetHeartCheck:重置心跳检测定时器。

实践

为了封装一个 WebSocket 类供全局使用,我们可以创建一个 Socket 类,提供必要的方法和功能。以下是一个简化的示例代码,展示了如何实现这个类:

// websocket.js
class Socket {
  constructor(options) {
    this.url = options.url;
    this.protocols = options.protocols;
    this.query = options.query;
    this.greet = options.greet;
    this.reconnectCount = 0;
    this.initSocket();
  }

  initSocket() {
    this.socket = new WebSocket(this.url);

    this.socket.onopen = () => {
      console.log(this.greet);
      // ... 触发 open 事件的回调 ...
    };

    this.socket.onclose = (event) => {
      // ... 处理关闭事件 ...
      if (event.code !== 1000) {
        // 非正常关闭
        this.reconnect();
      }
    };

    this.socket.onerror = (error) => {
      // ... 处理错误事件 ...
    };

    this.socket.onmessage = (message) => {
      // ... 处理接收到的消息 ...
    };
  }

  reconnect() {
    this.reconnectCount++;
    // ... 实现重连逻辑 ...
  }

  sendMessage(data) {
    this.socket.send(JSON.stringify(data));
  }

  closeSocket() {
    this.socket.close();
  }

  heartCheckStart() {
    // ... 实现心跳检测 ...
  }

  clearHeartCheck() {
    // ... 清除心跳检测定时器 ...
  }

  resetHeartCheck() {
    // ... 重置心跳检测定时器 ...
  }
}

// 导出 Socket 类
export default Socket;

说明

  1. 构造函数:接收配置选项并初始化 WebSocket 连接。

  2. 事件处理:处理 onopenoncloseonerroronmessage 事件。

  3. 重连机制:在连接关闭时,如果不是正常关闭,则尝试重连。

  4. 消息发送:提供 sendMessage 方法以发送消息。

  5. 心跳检测:提供心跳检测相关的方法。

你可以根据具体需求进一步扩展和修改这个类。


http://www.kler.cn/a/587492.html

相关文章:

  • Vue 中如何实现自定义指令?
  • 《DeepSeek 开源 DeepGEMM:开启AI计算新时代的密钥》:此文为AI自动生成
  • 变量赋值汇编
  • 【C】嵌入式的中断,理解
  • Modbus TCP到RTU:轻松转换指南!
  • docker mysql 默认配置文件路径
  • 架构思维:软件建模与架构设计的关键要点
  • mac安装navicat及使用
  • 聊聊langchain4j的AiServicesAutoConfig
  • vue里面使用什么组件和后端接口通讯
  • <meta content=“no-siteapp“ data-n-head=“ssr“ http-equiv=“Cache-Control“/>什么作用?
  • WPF CommunityToolkit.MVVM库的简单使用
  • 安全相关Python脚本
  • Qt介绍面试题一
  • Midjourney绘图参数详解:从基础到高级的全面指南
  • Java基礎2小時速成(上篇) - 掌握核心技术「卷」
  • 第十五届蓝桥杯C/C++B组拔河问题详解
  • Vision Transformer (ViT):将Transformer带入计算机视觉的革命性尝试(代码实现)
  • 7年全栈开发经验 · 兼职技术合作
  • ShenNiusModularity项目源码学习(16:ShenNius.Admin.Mvc项目分析-1)