在这里插入图片描述

🚀 从零开始打造一个WebSocket客户端库:websocket-fruge365

📖 前言

在现代Web开发中,实时通信已经成为不可或缺的功能。无论是聊天应用、实时数据监控,还是在线协作工具,WebSocket都扮演着重要角色。然而,原生的WebSocket API使用起来相对复杂,缺乏自动重连、错误处理等实用功能。

今天,我将分享如何从零开始打造一个功能完善的WebSocket客户端库 —— websocket-fruge365

🎯 项目目标

在开始编码之前,我们先明确这个库要解决的问题:

  • 简化API:提供更简洁易用的接口
  • 自动重连:网络断开时自动尝试重连
  • 错误处理:完善的错误处理机制
  • TypeScript支持:提供完整的类型定义
  • 跨平台:同时支持浏览器和Node.js环境

🛠️ 技术选型

  • 语言:JavaScript (ES6+)
  • 模块系统:ES Modules
  • 类型定义:TypeScript Declaration Files
  • 包管理:npm
  • Node.js支持:ws库

🏗️ 核心架构设计

1. 状态管理

let socket = null;
let handleMessage = null;
let handleErr = null;
let reconnectAttempts = 0;
let maxReconnectAttempts = 5;
let reconnectInterval = 3000;
let isManualClose = false;
let originalUrl = '';
let originalToken = null;

2. 核心连接函数

function initSocket(url, token = null) {if (typeof WebSocket === "undefined") {console.error("初始化失败, 不支持使用WebSocket");return false;}const protocols = token ? [token] : undefined;try {socket = new WebSocket(url, protocols);} catch (error) {console.error('WebSocket连接创建失败:', error);return false;}// 绑定事件处理器socket.onopen = socketOnOpen;socket.onmessage = socketOnMessage;socket.onerror = socketOnError;socket.onclose = socketOnClose;return true;
}

3. 自动重连机制

socket.onclose = (e) => {console.log('连接关闭', e.code, e.reason);if (!isManualClose && reconnectAttempts < maxReconnectAttempts) {setTimeout(() => {reconnectAttempts++;console.log(`尝试重连 (${reconnectAttempts}/${maxReconnectAttempts})`);initSocket(originalUrl, originalToken);}, reconnectInterval);}
};

🔧 关键功能实现

1. 连接管理

export function connectSocket(url, options = {}) {if (!url) {console.error('WebSocket URL不能为空');return false;}const {token = null,onMessage = null,onError = null,maxReconnectAttempts: maxAttempts = 5,reconnectInterval: interval = 3000} = options;// 设置全局配置maxReconnectAttempts = maxAttempts;reconnectInterval = interval;if (onMessage) handleMessage = onMessage;if (onError) handleErr = onError;// 保存原始参数用于重连originalUrl = url;originalToken = token;return initSocket(url, token);
}

2. 消息发送

export function sendMessage(data) {if (!socket) {console.error('WebSocket未初始化');return false;}if (socket.readyState === WebSocket.OPEN) {try {const message = typeof data === 'string' ? data : JSON.stringify(data);socket.send(message);return true;} catch (error) {console.error('发送消息失败:', error);return false;}} else {console.warn('WebSocket连接未就绪, 当前状态:', socket.readyState);return false;}
}

3. 状态检查

export function getSocketState() {if (!socket) return 'CLOSED';switch (socket.readyState) {case WebSocket.CONNECTING: return 'CONNECTING';case WebSocket.OPEN: return 'OPEN';case WebSocket.CLOSING: return 'CLOSING';case WebSocket.CLOSED: return 'CLOSED';default: return 'UNKNOWN';}
}export function isConnected() {return socket && socket.readyState === WebSocket.OPEN;
}

📝 TypeScript类型定义

为了提供更好的开发体验,我们添加了完整的TypeScript类型定义:

export interface WebSocketOptions {/** 可选的token参数 */token?: string;/** 获取websocket传过来的数据后的处理函数 */onMessage?: (event: MessageEvent) => void;/** websocket连接出错后的处理函数 */onError?: (error: Event) => void;/** 最大重连次数,默认5次 */maxReconnectAttempts?: number;/** 重连间隔,默认3000ms */reconnectInterval?: number;
}export type SocketState = 'CONNECTING' | 'OPEN' | 'CLOSING' | 'CLOSED' | 'UNKNOWN';

🎨 使用示例

基本用法

import { connectSocket, sendMessage, closeSocket } from 'websocket-fruge365';// 连接WebSocket
connectSocket('ws://localhost:8080', {onMessage: (event) => {console.log('收到消息:', event.data);},onError: (error) => {console.error('连接错误:', error);}
});// 发送消息
sendMessage({ type: 'hello', message: 'Hello WebSocket!' });// 关闭连接
closeSocket();

Vue3中使用

<script setup>
import { connectSocket, sendMessage, closeSocket } from 'websocket-fruge365';
import { onMounted, onUnmounted } from 'vue';const initWebSocket = () => {connectSocket('ws://localhost:8080', {onMessage: (event) => {console.log('收到消息:', event.data);},onError: (error) => {console.error('连接错误:', error);}});// 等待连接建立后发送消息setTimeout(() => {sendMessage({ type: 'hello', message: 'Hello from Vue3!' });}, 1000);
}onMounted(() => {initWebSocket();
});onUnmounted(() => {closeSocket();
});
</script>

聊天应用示例

import { connectSocket, sendMessage, isConnected } from 'websocket-fruge365';class ChatClient {constructor(url, userId) {this.userId = userId;this.connect(url);}connect(url) {connectSocket(`${url}?userId=${this.userId}`, {onMessage: this.handleMessage.bind(this),onError: this.handleError.bind(this),maxReconnectAttempts: 5,reconnectInterval: 3000});}handleMessage(event) {const message = JSON.parse(event.data);console.log(`${message.user}: ${message.text}`);}sendChatMessage(text) {if (isConnected()) {sendMessage({type: 'chat',user: this.userId,text: text,timestamp: Date.now()});}}
}

📦 发布到npm

1. 准备package.json

{"name": "websocket-fruge365","version": "1.0.5","description": "一个简单易用的WebSocket客户端库,支持自动重连、错误处理和消息管理","main": "index.js","module": "index.js","type": "module","files": ["index.js","socket.js","README.md","types.d.ts"],"keywords": ["websocket","socket","realtime","client","reconnect","javascript","browser","nodejs"],"author": "fruge365","license": "MIT"
}

2. 发布流程

# 登录npm
npm login# 发布包
npm publish

🚀 项目亮点

1. 简洁的API设计

  • 只需要一个函数调用即可建立连接
  • 参数通过options对象传递,清晰明了
  • 提供了常用的工具函数

2. 健壮的错误处理

  • 连接失败时的自动重连
  • 详细的错误日志输出
  • 优雅的降级处理

3. 完善的开发体验

  • 完整的TypeScript类型定义
  • 详细的文档和示例
  • 支持多种使用场景

4. 跨平台兼容

  • 浏览器环境原生支持
  • Node.js环境通过ws库支持
  • 统一的API接口

🔍 遇到的挑战与解决方案

1. 重连时参数丢失问题

问题:初始连接失败后,重连时token等参数会丢失。

解决方案:在连接时保存原始参数,重连时使用保存的参数。

// 保存原始参数用于重连
originalUrl = url;
originalToken = token;

2. Node.js环境兼容性

问题:Node.js环境没有原生WebSocket支持。

解决方案:使用ws库,并在文档中说明使用方法。

// Node.js环境
global.WebSocket = require('ws');
import { connectSocket } from 'websocket-fruge365';

3. API设计的简化

问题:最初的API设计过于复杂,有params参数等冗余设计。

解决方案:简化API,移除不必要的参数,让用户直接在URL中包含查询参数。

📈 性能优化

  1. 内存管理:及时清理事件监听器和定时器
  2. 错误边界:添加try-catch保护关键代码
  3. 状态检查:发送消息前检查连接状态
  4. 参数验证:对输入参数进行有效性检查

🔮 未来规划

  • 添加心跳检测机制
  • 支持消息队列和批量发送
  • 添加连接池管理
  • 提供更多的配置选项
  • 添加单元测试覆盖

📚 总结

通过这个项目,我学到了:

  1. API设计的重要性:简洁易用的API是库成功的关键
  2. 错误处理的必要性:完善的错误处理能大大提升用户体验
  3. 文档的价值:好的文档能让用户快速上手
  4. 类型定义的作用:TypeScript支持能提升开发效率
  5. 测试的重要性:充分的测试能保证代码质量

🔗 相关链接

  • GitHub仓库:https://github.com/fruge365/WebSocket
  • npm包:https://www.npmjs.com/package/websocket-fruge365
  • 作者博客:https://fruge365.blog.csdn.net/

🎉 结语

开发一个npm包是一个很好的学习过程,不仅能加深对技术的理解,还能为开源社区做出贡献。希望这个WebSocket客户端库能帮助到更多的开发者,也欢迎大家提出建议和贡献代码!

如果这个项目对你有帮助,请给个 ⭐ Star 支持一下!


关于作者

我是fruge365,一名热爱技术的前端开发者。专注于Web开发、JavaScript、Vue.js等技术领域。

  • GitHub: https://github.com/fruge365
  • CSDN博客: https://fruge365.blog.csdn.net/

欢迎关注我的技术分享!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/95545.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/95545.shtml
英文地址,请注明出处:http://en.pswp.cn/web/95545.shtml

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

相关文章

rocketmq批量执行跑批任务报错

rocketmq批量执行跑批任务&#xff0c;报下面的错误&#xff0c;怎么处理一下呢&#xff1f;是修改配置还是修改代码还是&#xff1f; org.apache.rocketmq.client.exception.MQBrokerException: CODE: 215 DESC: [FLOW]client has exhausted the send quota for the current …

大语言模型(LLM)简介与应用分享

1. 什么是大语言模型&#xff08;LLM&#xff09; 大语言模型&#xff08;Large Language Model&#xff0c;简称 LLM&#xff09;是基于 深度学习 和 海量文本数据 训练而成的人工智能模型。 采用 Transformer 架构参数规模巨大&#xff08;数十亿到数千亿&#xff09;能够 理…

【算法笔记】选择排序、插入排序、冒泡排序、二分查找问题

算法的笔记&#xff0c;直接上代码&#xff0c;思路和问题这些&#xff0c;都在代码注释上面 1、工具类 为了生成测试代码和比较器&#xff0c;专门写了一个数组工具类&#xff0c;代码如下&#xff1a; /*** 数组工具类*/ public class ArrUtil {/*** 生成随机数组* 长度是[0,…

行业分享丨基于SimSolid的大型汽车连续冲压模具刚度分析

*本文投稿自机械零部件制造业用户 汽车连续模具的刚度直接决定了冲压件质量&#xff08;尺寸精度、表面缺陷&#xff09;与模具寿命。传统有限元分析&#xff08;FEA&#xff09;在面对大型复杂模具装配体时&#xff0c;存在网格划分困难、计算资源消耗大、周期长等瓶颈。本文以…

用AI生成的html页面设计放到到Axure上实现再改造的方法

要将 AI 生成的 HTML 原型导入 Axure&#xff0c;该方法的核心逻辑是以 Figma 为 “中间桥梁”&#xff08;因 Axure 无法直接读取 HTML&#xff0c;需通过 Figma 转换格式&#xff09;&#xff0c;分 3 步即可完成&#xff0c;以下是详细操作指南&#xff08;含每步目标、具体…

从入门到实战:Linux sed命令全攻略,文本处理效率翻倍

从入门到实战&#xff1a;Linux sed命令全攻略&#xff0c;文本处理效率翻倍 文章目录从入门到实战&#xff1a;Linux sed命令全攻略&#xff0c;文本处理效率翻倍一、认识sed&#xff1a;什么是流编辑器&#xff1f;二、吃透sed工作原理&#xff1a;为什么它能高效处理文本&am…

TIOBE 8月编程语言榜深度解析:Python占比突破26%,Perl成最大黑马

根据TIOBE最新发布的2025年8月编程语言排行榜&#xff0c;一场静默的技术变革正在上演&#xff1a;Python以26.14%的占比首次突破26%大关&#xff0c;连续12个月稳居榜首。这一数据不仅刷新了Python自身的历史纪录&#xff0c;更成为TIOBE指数自2001年创立以来的最高单语言占比…

从发现到恢复,看瑞数信息如何构建“抗毁重构”实战路径

在信息化社会&#xff0c;“韧性”“弹性”这些词汇常被用来形容系统抵御和应对风险的能力&#xff0c;但对于身处关键基础设施行业的运营者来说&#xff0c;这些概念往往过于抽象&#xff0c;难以直接指导实践。 相比之下&#xff0c;“抗毁重构”更具画面感。它不仅是一个管理…

深入理解 jemalloc:从内存分配机制到技术选型

在高性能服务&#xff08;如数据库、缓存、JVM&#xff09;的底层优化中&#xff0c;内存分配效率直接影响系统整体性能。本文将从操作系统底层的malloc机制切入&#xff0c;详解 jemalloc 的设计理念、开源应用场景、实战案例&#xff0c;技术选型分析 一、操作系统底层的内存…

websoket使用记录

1.项目使用记录1.医疗项目中渲染回收柜温湿度&#xff0c;需要实时更新2.回收柜安瓿回收和余液回收时&#xff0c;需要前端发送指令给回收柜&#xff0c;比如开门、关门等。还需要收到回收柜结果&#xff0c;比如回收的药品信息等。我项目中用的是浏览器自带的websoket&#xf…

DevOps篇之通过GitLab CI 流水线实现k8s集群中helm应用发布

一. 设计思路 构建一个 GitLab CI 流水线&#xff0c;并且要集成到 K8s 集群中的 Helm 应用发布流程。首先&#xff0c;需要了解 GitLab CI 的基本结构&#xff0c;比如.gitlab-ci.yml 文件的配置&#xff0c;包括 stages、jobs、变量设置等。然后&#xff0c;结合之前讨论的 H…

详尽 | Deeplabv3+结构理解

https://arxiv.org/pdf/1802.02611.pdf https://link.springer.com/chapter/10.1007/978-3-319-10578-9_23 目录 Deeplabv3 Encoder部分 Decoder部分 补充摘要 SPP 空间金字塔池化层模块 Dilated/Atrous Conv 空洞卷积 Deeplabv3 deeplab-v3是语义分割网络&#xff0c;组…

【51单片机】【protues仿真】基于51单片机音乐盒(8首歌曲)系统

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 一、主要功能 1、数码管显示当前歌曲序号 2、按键切换歌曲和播放暂停​ 3、内置8首音乐 二、使用步骤 基于51单片机的音乐盒是一种能够存储和播放多首歌曲的电子设备&#xff0c;通过定时器产…

@ZooKeeper 详细介绍部署与使用详细指南

文章目录 **ZooKeeper 详细介绍、部署与使用** 1. 概述 & 核心介绍 1.1 什么是 ZooKeeper? 1.2 核心特性 1.3 核心概念 1.4 典型应用场景 2. 部署 (以 3 节点集群为例) 2.1 环境准备 2.2 安装步骤 (在所有节点执行) 2.3 启动与停止集群 2.4 防火墙配置 (如果开启) 3. 基本…

腾讯Hunyuan-MT-7B翻译模型完全指南:2025年开源AI翻译的新标杆

&#x1f3af; 核心要点 (TL;DR) 突破性成就&#xff1a;腾讯混元MT-7B在WMT25全球翻译竞赛中获得30/31项第一名双模型架构&#xff1a;Hunyuan-MT-7B基础翻译模型 Hunyuan-MT-Chimera-7B集成优化模型广泛语言支持&#xff1a;支持33种语言互译&#xff0c;包括5种中国少数民…

Web 集群高可用全方案:Keepalived+LVS (DR) 负载均衡 + Apache 服务 + NFS 共享存储搭建指南

文章目录Keepalived LVS&#xff08;DR&#xff09; Apache NFS项目背景业务场景与核心需求传统架构的痛点与局限技术方案的选型逻辑项目价值与预期目标项目实践项目环境基础配置配置 router配置免密登录-可选配置 nfs配置 web配置 LVS-RS配置 HA 和 LVS-DS配置 ha1配置 ha2测…

Prometheus监控预警系统深度解析:架构、优劣、成本与竞品

目录 一、Prometheus是什么&#xff1f;核心定位与架构 二、竞品分析&#xff08;Prometheus vs. Zabbix vs. Nagios vs. Commercial SaaS&#xff09; 三、部署成本分析 四、服务器资源消耗分析 五、给您的最终建议 一、Prometheus是什么&#xff1f;核心定位与架构 Prom…

Nginx反向代理及配置

Nginx反向代理 二级域名系统 顾名思义&#xff0c;我们有很多的这个不同的二级域名的用户来访问我们&#xff0c;比如说微博。它有一个主域名weibo.com。如果我叫一鸣,申请了一个微博&#xff0c;然后我就可以在微博这个主系统上申请一个二级域名来访问我微博的主页&#xff0…

嵌入式系统通信总线全景探秘:从板内到云端

引言 在嵌入式系统设计中&#xff0c;选择合适的通信总线是决定系统性能、成本和可靠性的关键因素。从简单的芯片间通信到复杂的工业网络&#xff0c;不同的总线技术各司其职&#xff0c;形成了嵌入式世界的"交通网络"。本文将深入探讨五种经典且重要的通信技术&…

2022版Unity创建时没有2D灯光(2D Light),没有Global LIght2D怎么办?

简单来说就是你的渲染管线没有升级到URP管线&#xff0c;所以才没有这些2D灯光 如果你的创建灯光和我一样&#xff0c;没有红线划掉的部分&#xff0c;说明你和我的问题一样&#xff0c;看下面的教程可以解决。 1. 确保Unity版本 确保你的Unity版本至少为2019.4或更高版本&…