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

一个WebSocket的前端封装类

一、概述

实现一个MyWebSocket的自定义 WebSocket 类,用于建立与服务器的 WebSocket 连接,并提供了一系列方法来处理连接状态、发送和接收消息、自动重连等功能。该类可以方便地在前端项目中实现与服务器的实时通信。

二、实现思路

  1. 类的构造函数接收 URL 和可选的配置参数,初始化 WebSocket 连接所需的属性,如连接 URL、重连间隔、最大重连次数、日志级别和各种回调函数等。
  2. 通过_initWebsocket方法初始化 WebSocket 连接,设置连接的打开、关闭、错误和消息接收等事件的处理函数。
  3. 提供了getStatus方法用于获取 WebSocket 的连接状态。
  4. then方法用于设置接收消息时的回调函数。
  5. sendMessage方法用于向服务器发送 JSON 格式的消息,并在发送前自动添加用户信息(如果消息中没有operatingUserId,则从localStorage中获取userId添加到消息中)。
  6. 当连接出现错误或关闭时,启动自动重连机制,尝试在一定时间间隔后重新建立连接。

三、方法解析

  1. constructor:初始化类的属性,合并默认配置和传入的配置选项,调用_initWebsocket方法开始建立连接。
  2. getStatus:返回 WebSocket 的当前连接状态,通过readyState属性判断连接的状态。
  3. then:设置接收消息时的回调函数,该回调函数在_websocketmessage方法中被调用。
  4. sendMessage:在发送消息前,先检查消息是否为有效的 JSON 对象,如果不是则抛出错误。然后调用_wrapUserInfo方法添加用户信息,最后将消息转换为 JSON 字符串并通过 WebSocket 发送。
  5. _wrapUserInfo:检查消息中是否存在operatingUserId,如果不存在则从localStorage中获取userId并添加到消息中。
  6. _isJSON:判断一个对象是否为有效的 JSON 对象,通过检查对象的类型和键的数量来判断。
  7. _initWebsocket:尝试建立 WebSocket 连接,设置连接的各种事件处理函数。如果建立连接过程中出现错误,则启动重连机制。
  8. _websocketopen_websocketerror_websocketclose_websocketmessage:分别处理 WebSocket 的打开、错误、关闭和消息接收事件,调用相应的回调函数和日志方法。
  9. _startReconnect:启动重连机制,设置定时器,在一定时间间隔后尝试重新建立连接,直到达到最大重连次数。
  10. _logInfo_logWarn_logError:根据日志级别打印不同类型的日志信息。

四、注意事项

  1. 确保在使用该类时,提供正确的 WebSocket 服务器 URL 和有效的配置选项。
  2. 注意处理可能出现的错误,如消息不是有效的 JSON 对象、获取tokenuserId失败等情况。
  3. 在使用自动重连功能时,要考虑到重连次数和时间间隔的合理性,避免过度频繁的重连对服务器造成压力。
  4. 确保在合适的时机调用then方法设置接收消息的回调函数,以便正确处理接收到的消息。
  5. 注意在发送消息前,确保消息是有效的 JSON 对象,否则会抛出错误。

五、使用示例

this.MyWebSocket = new MyWebSocket("http://ip:port/websocket");
// 接收消息
this.MyWebSocket.then((e) => {console.log(e);
});
// 发送消息
this.websocket.sendMessage(JSON.stringify({"info": "我正在操作页面..." }));

六、附源码

const _OPERATING_USER_ID = "userId";
/*** WebSocket Custom Class*/
class MyWebSocket {_url = "";_ws = null;_then = null;_options = null;_reconnectInterval = 2000;_reconnectTimeoutId = null;_reconnectAttempts = 0;_maxReconnectAttempts = 100;_logLevel = process.env.NODE_ENV === "development" ? "info" : "warning";_connectedCallback = null;_disconnectedCallback = null;_errorCallback = null;_messageReceivedCallback = null;/*** Constructor for MyWebSocket class. Initializes a new WebSocket connection with the provided URL and options.** @param {string} url - The WebSocket server URL.* @param {Object} [options={}] - Optional configuration options for the WebSocket connection.* @param {number} [options.reconnectInterval=2000] - The time interval (in milliseconds) between reconnection attempts.* @param {number} [options.maxReconnectAttempts=100] - The maximum number of reconnection attempts before giving up.* @param {string} [options.logLevel="info"] - The log level for WebSocket events. Can be "off", "error", "warn", "info", or "debug".* @param {function} [options.connectedCallback] - A callback function to be executed when the WebSocket connection is established.* @param {function} [options.disconnectedCallback] - A callback function to be executed when the WebSocket connection is closed.* @param {function} [options.errorCallback] - A callback function to be executed when an error occurs during the WebSocket connection.* @param {function} [options.messageReceivedCallback] - A callback function to be executed when a message is received from the WebSocket server.*/constructor(url, options = {}) {this._url = url;this._options = {reconnectInterval: this._reconnectInterval,maxReconnectAttempts: this._maxReconnectAttempts,logLevel: "info",...options,};this._reconnectInterval = this._options.reconnectInterval;this._maxReconnectAttempts = this._options.maxReconnectAttempts;this._logLevel = this._options.logLevel;this._connectedCallback = this._options.connectedCallback;this._disconnectedCallback = this._options.disconnectedCallback;this._errorCallback = this._options.errorCallback;this._messageReceivedCallback = this._options.messageReceivedCallback;this._initWebsocket();}/*** Retrieves the readyState of the WebSocket connection.** @returns {number} The readyState of the WebSocket connection.* The readyState attribute represents the state of the connection:* - 0: CONNECTING: The connection is not yet open.* - 1: OPEN: The connection is open and ready to communicate.* - 2: CLOSING: The connection is in the process of closing.* - 3: CLOSED: The connection is closed or couldn't be opened.*/getStatus() {return this._ws.readyState;}/*** Sets a callback function to be executed when a message is received from the WebSocket server.** @param {function} callback - The callback function to be executed when a message is received.* The callback function will receive two parameters:* - {Object} msg - The parsed JSON message received from the server.* - {MessageEvent} event - The original MessageEvent object received from the WebSocket.** @returns {void}*/then(callback) {this._then = callback;}/*** Sends a JSON message to the WebSocket server.** @param {Object} message - The JSON message to be sent.* @throws {Error} Throws an error if the message is not a valid JSON object.* @returns {void}*/sendMessage(message) {if (!this._isJSON(message)) {throw new Error(" could not send non JSON message");}this._wrapUserInfo(message);this._ws.send(JSON.stringify(message));}/*** Wraps the user information in the given message object.* If the message does not contain the operatingUserId, it retrieves the userId from localStorage and adds it to the message.** @param {Object} message - The message object to be sent to the WebSocket server.* @returns {void} The function modifies the message object in-place.** @example* const message = {*   type: 'chat',*   content: 'Hello, WebSocket!'* };* _wrapUserInfo(message);* // After execution, message will be:* // {* //   type: 'chat',* //   content: 'Hello, WebSocket!',* //   operatingUserId: '12345'* // }*/_wrapUserInfo(message) {if (!(_OPERATING_USER_ID in message)) {message.operatingUserId = localStorage.getItem("userId");}}_isJSON(obj) {if (typeof obj !== "object") {return false;}try {return Object.keys(obj).length > 0 && typeof obj === "object";} catch (e) {return false;}}/*** Initializes a new WebSocket connection with the provided URL.** @private* @memberof MyWebSocket* @returns {void}** @throws {Error} Throws an error if there is an issue initializing the WebSocket connection.*/_initWebsocket() {// config.headers["Authorization"] = localStorage.getItem("token");try {const token = localStorage.getItem("token");if (!token) {this._logError("get token failed.");}const url = `${this._url}?Authorization=${token}`;this._ws = new WebSocket(url);const that = this;this._ws.onopen = (e) => {return this._websocketopen(that, e);};this._ws.onclose = (e) => {return this._websocketclose(that, e);};this._ws.onmessage = (e) => {return this._websocketmessage(that, e);};this._ws.onerror = (e) => {return this._websocketerror(that, e);};} catch (error) {this._logError("Error initializing WebSocket: " + error.message);this._startReconnect();}}_websocketopen(that) {that._logInfo("websocket open");if (typeof that._connectedCallback === "function") {that._connectedCallback();}if (that._reconnectTimeoutId) {clearInterval(that._reconnectTimeoutId);that._reconnectTimeoutId = null;that._reconnectAttempts = 0;}}_websocketerror(that, event) {that._logError("websocket error: " + event.message);if (typeof that._errorCallback === "function") {that._errorCallback(event);}that._startReconnect();}_websocketclose(that, event) {that._logWarn("websocket closed: " + event.reason);if (typeof that._disconnectedCallback === "function") {that._disconnectedCallback(event);}that._startReconnect();}/*** Handles incoming messages from the WebSocket server.* Parses the received data as JSON and triggers the appropriate callback functions.** @param {MessageEvent} event - The original MessageEvent object received from the WebSocket.* @private* @memberof MyWebSocket* @returns {void}*/_websocketmessage(that, event) {let msg = {};try {msg = JSON.parse(event.data);} catch (e) {that._logError("websocket message parse error: " + e.message);}if (that._then && typeof that._then === "function") {that._then(msg, event);}if (typeof this._messageReceivedCallback === "function") {that._messageReceivedCallback(msg, event);}}/*** Initiates the reconnection process to the WebSocket server.* This function is called when the WebSocket connection is closed or encounters an error.* It checks if the maximum reconnection attempts have been reached, logs an error message if necessary,* and starts a timer to attempt reconnection after the specified interval.** @private* @memberof MyWebSocket* @returns {void}*/_startReconnect() {if (this._reconnectTimeoutId) {return;}this._reconnectTimeoutId = setInterval(() => {this._logInfo("Attempting to reconnect... Attempt " + (this._reconnectAttempts + 1));this._initWebsocket();this._reconnectAttempts++;if (this._reconnectAttempts >= this._maxReconnectAttempts) {this._logError("Max reconnect attempts reached. Giving up.");clearInterval(this._reconnectTimeoutId);return;}}, this._reconnectInterval);}/*** Logs an informational message to the console based on the log level.** @param {string} message - The informational message to be logged.* @returns {void}** @private* @memberof MyWebSocket*/_logInfo(message) {if (this._logLevel === "info" || this._logLevel === "debug") {console.log(message);}}/*** Logs a warning message to the console based on the log level.** @param {string} message - The warning message to be logged.* @returns {void}** @private* @memberof MyWebSocket*/_logWarn(message) {if (this._logLevel === "warn" || this._logLevel === "info" || this._logLevel === "debug") {console.warn(message);}}/*** Logs an error message to the console based on the log level.** @param {string} message - The error message to be logged.* @returns {void}** @private* @memberof MyWebSocket*/_logError(message) {if (this._logLevel !== "off") {console.error(message);}}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • RocketMQ 消费方式
  • vue组件之间的数据共享
  • vite 使用飞行器仪表示例
  • IDEA 2024.3 EAP新特征早览!
  • C#基础(16)实践:学生成绩管理系统
  • 基于PHP+MySQL组合开发的在线客服源码系统 聊天记录实时保存 带完整的安装代码包以及搭建部署教程
  • 【JVM】垃圾回收机制|死亡对象的判断算法|垃圾回收算法
  • 学习笔记——RegNet:Designing Network Design Spaces
  • (k8s)kubernetes集群基于Containerd部署
  • 2024年开放式蓝牙耳机十大排名震撼揭晓!哪款开放式耳机是音质王者?
  • 从零开始学习Linux(13)---多线程
  • Flutter iOS混淆打包
  • python中ocr图片文字识别样例(一)
  • 低级编程语言和高级编程语言
  • 【ArcGIS微课1000例】0121:面状数据共享边的修改方法
  • [case10]使用RSQL实现端到端的动态查询
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • CSS居中完全指南——构建CSS居中决策树
  • JS笔记四:作用域、变量(函数)提升
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • leetcode388. Longest Absolute File Path
  • Nacos系列:Nacos的Java SDK使用
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • SegmentFault 2015 Top Rank
  • Selenium实战教程系列(二)---元素定位
  • Spring Boot快速入门(一):Hello Spring Boot
  • SpringBoot 实战 (三) | 配置文件详解
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • vue:响应原理
  • WePY 在小程序性能调优上做出的探究
  • 阿里研究院入选中国企业智库系统影响力榜
  • 包装类对象
  • 服务器从安装到部署全过程(二)
  • 基于 Babel 的 npm 包最小化设置
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 算法之不定期更新(一)(2018-04-12)
  • 微服务入门【系列视频课程】
  • 微信小程序实战练习(仿五洲到家微信版)
  • 由插件封装引出的一丢丢思考
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​必胜客礼品卡回收多少钱,回收平台哪家好
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • #Z0458. 树的中心2
  • (11)MATLAB PCA+SVM 人脸识别
  • (2)Java 简介
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (52)只出现一次的数字III
  • (poj1.2.1)1970(筛选法模拟)
  • (pycharm)安装python库函数Matplotlib步骤
  • (差分)胡桃爱原石
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)