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

前端WebSocket应用——聊天实时通信的基本配置

使用 WebSocket 实现实时通信的 Vue 应用
  • 前言
  • 1. WebSocketService 类
    • 1.1 类属性
    • 1.2 构造函数和连接初始化
    • 1.3 WebSocket 连接
    • 1.4 事件处理方法
    • 1.5 发送和关闭 WebSocket 消息
    • 1.6 状态查询与回调注册
    • 1.7 完整代码
  • 2. 在 Vue 组件中使用 WebSocketService
    • 2.1 定义 WebSocket URL
    • 2.2 实例化 WebSocketService
    • 2.3 生命周期钩子
  • 3. 总结

前言

在现代 Web 应用中,实时通信是提升用户体验的重要因素之一。WebSocket 协议提供了一种在客户端和服务器之间建立持久连接的方式,使得双向数据传输成为可能。本文将通过两个代码段,展示如何在 Vue 应用中使用 WebSocket 实现实时消息接收和发送。

1. WebSocketService 类

首先,我们定义一个 WebSocketService 类,用于管理 WebSocket 连接及其相关操作。以下是该类的实现:

1.1 类属性

  • socket: WebSocket | null: 存储 WebSocket 实例,用于与服务器进行实时通信。初始值为 null,在调用 connect() 方法时创建 WebSocket 实例。

  • count: number: 计数器,用于统计接收到的 WebSocket 消息的数量。每次接收到新消息时,计数器会自增。

  • token: string: 从用户状态中提取的令牌(token),用于认证。通过 useUserStore() 获取用户的 token 并保存下来,用于 WebSocket 的连接和认证。

  • isConnected: boolean: 表示 WebSocket 是否成功连接到服务器。初始值为 false,在 onOpen() 方法中连接成功后设置为 true。

  • onMessageCallback: ((message: any) => void) | null: 用于存储一个回调函数,当 WebSocket 接收到消息时会调用此回调函数并传递消息内容。初始值为 null,通过 onMessageReceived() 方法注册。

    private socket: WebSocket | null = null; // 存储 WebSocket 实例
    private count: number = 0; // 统计接收到的消息数量
    private token: string; // 用于存储从用户状态中获取的令牌 (token)
    private isConnected: boolean = false; // 用于判断是否连接成功
    private onMessageCallback: ((message: any) => void) | null = null; // 消息回调函数

1.2 构造函数和连接初始化

  • 构造函数接受一个 socketUrl 参数,用于指定 WebSocket 服务器的地址。

  • 使用 useUserStore() 从用户状态中获取 token,存储在 this.token 中。

  • 调用 connect(socketUrl) 方法与服务器建立 WebSocket 连接。

    constructor(socketUrl: string) {
    const userStore = useUserStore();
    this.token = userStore.token;
    this.connect(socketUrl);
    }

1.3 WebSocket 连接

connect(socketUrl) 方法创建一个新的 WebSocket 实例,传入 socketUrl 和 this.token 作为子协议,用于与服务器通信。
为 WebSocket 注册了以下事件监听器:

  • open: 当连接成功时触发,调用 onOpen() 方法。

  • message: 当接收到服务器消息时触发,调用 onMessage() 方法。

  • error: 当发生错误时触发,调用 onError() 方法。

  • close: 当连接关闭时触发,调用 onClose() 方法。

    private connect(socketUrl: string) {
    this.socket = new WebSocket(socketUrl, this.token);

    this.socket.addEventListener('open', (event) => {this.onOpen(event);
    });this.socket.addEventListener('message', (event) => {this.onMessage(event);
    });this.socket.addEventListener('error', (event) => {this.onError(event);
    });this.socket.addEventListener('close', (event) => {this.onClose(event);
    });
    

    }

1.4 事件处理方法

onOpen(event: Event): 在 WebSocket 连接成功后触发。

  • 发送认证信息(Authorization: Bearer token)给服务器,用于身份验证。

  • 将 isConnected 设置为 true,表示连接成功。

  • 打印 “WebSocket connection established” 到控制台。

    private onOpen(event: Event) {
    if (this.socket) {
    this.socket.send('Authorization: Bearer ’ + this.token);
    this.isConnected = true;
    console.log(“WebSocket connection established”);
    }
    }

onMessage(event: MessageEvent): 当 WebSocket 接收到消息时触发。

  • 增加消息计数器 count。

  • 如果注册了 onMessageCallback,则调用回调函数并传递消息数据。

    private onMessage(event: MessageEvent) {
    this.count++;
    console.log(‘Received:’, this.count);

    const messageData = event.data;if (this.onMessageCallback) {this.onMessageCallback(messageData);
    }
    

    }

onError(event: Event): 当 WebSocket 出现错误时触发。

  • 打印错误信息到控制台,帮助调试。

    private onError(event: Event) {
    console.error(“WebSocket error observed:”, event);
    }

onClose(event: CloseEvent): 当 WebSocket 连接关闭时触发。

  • 将 isConnected 设置为 false,表示连接已断开。

  • 打印连接关闭信息到控制台。

    private onClose(event: CloseEvent) {
    console.log(“WebSocket closed:”, event);
    this.isConnected = false;
    }

1.5 发送和关闭 WebSocket 消息

sendMessage(message: string): 用于发送消息到服务器。

  • 如果 WebSocket 连接状态为 OPEN,则发送消息。

  • 否则打印错误信息并显示 WebSocket 当前的 readyState。

    public sendMessage(message: string) {
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
    this.socket.send(message);
    } else {
    console.error(“WebSocket is not open. ReadyState:”, this.socket?.readyState);
    }
    }

close(): 手动关闭 WebSocket 连接。

public close() {if (this.socket) {this.socket.close();}
}

1.6 状态查询与回调注册

isConnectedSuccessfully(): 用于查询 WebSocket 当前的连接状态,返回 true 或 false。

public isConnectedSuccessfully(): boolean {return this.isConnected;
}

onMessageReceived(callback: (message: any) => void): 注册一个消息处理回调函数,当 WebSocket 接收到消息时触发该回调函数。

public onMessageReceived(callback: (message: any) => void) {this.onMessageCallback = callback;
}

1.7 完整代码

import { useUserStore } from "../module/user";class WebSocketService {private socket: WebSocket | null = null; // 存储 WebSocket 实例private count: number = 0; // 统计接收到的消息数量private token: string; // 用于存储从用户状态中获取的令牌 (token)private isConnected: boolean = false; // 用于判断是否连接成功private onMessageCallback: ((message: any) => void) | null = null; // 消息回调函数constructor(socketUrl: string) {const userStore = useUserStore();this.token = userStore.token;this.connect(socketUrl);}private connect(socketUrl: string) {this.socket = new WebSocket(socketUrl, this.token);this.socket.addEventListener('open', (event) => {this.onOpen(event);});this.socket.addEventListener('message', (event) => {this.onMessage(event);});this.socket.addEventListener('error', (event) => {this.onError(event);});this.socket.addEventListener('close', (event) => {this.onClose(event);});}private onOpen(event: Event) {if (this.socket) {this.socket.send('Authorization: Bearer ' + this.token);this.isConnected = true; // 连接成功console.log("WebSocket connection established");}}private onMessage(event: MessageEvent) {this.count++;console.log('Received:', this.count);const messageData = event.data; // 获取消息内容if (this.onMessageCallback) {this.onMessageCallback(messageData); // 调用回调函数,传递消息内容}}private onError(event: Event) {console.error("WebSocket error observed:", event);}private onClose(event: CloseEvent) {console.log("WebSocket closed:", event);this.isConnected = false; // 连接关闭}public sendMessage(message: string) {if (this.socket && this.socket.readyState === WebSocket.OPEN) {this.socket.send(message);} else {console.error("WebSocket is not open. ReadyState:", this.socket?.readyState);}}public close() {if (this.socket) {this.socket.close();}}public isConnectedSuccessfully(): boolean {return this.isConnected;}public onMessageReceived(callback: (message: any) => void) {this.onMessageCallback = callback;}
}export default WebSocketService;

2. 在 Vue 组件中使用 WebSocketService

在 Vue 组件中,我们可以利用 onMountedonBeforeUnmount 生命周期钩子来管理 WebSocket 的生命周期。以下是如何在 Vue 组件中使用 WebSocketService 的示例代码:

import { onMounted, onBeforeUnmount } from 'vue';
import WebSocketService from '../../store/module/websocket';const socketUrl = 'http://123.123.123.123:端口号/ws';
const websocketService = new WebSocketService(socketUrl);onMounted(() => {// 接收消息websocketService.onMessageReceived((message) => {console.log("New message received:", message);// 在这里处理接收到的消息});
});// 关闭 WebSocket 连接
onBeforeUnmount(() => {websocketService.close();console.log("WebSocket connection closed.");
});

2.1 定义 WebSocket URL

const socketUrl = http://123.123.123.123:8088/ws’; 这一行定义了一个字符串 socketUrl,它表示要连接的 WebSocket 服务器的 URL。这个 URL 指向一个运行在 IP 地址为 123.123.123.123 的服务器上,端口为 8088,并且使用 /ws 路径。

2.2 实例化 WebSocketService

const websocketService = new WebSocketService(socketUrl); 这一行创建了 WebSocketService 类的一个实例,并将之前定义的 socketUrl 作为参数传递给构造函数。

2.3 生命周期钩子

  • onMounted: 当组件挂载时,注册接收消息的回调函数。这允许我们在接收到新消息时进行相应处理。
  • onBeforeUnmount: 当组件卸载时,调用 close 方法关闭 WebSocket 连接,以释放资源。

3. 总结

通过上述代码,我们实现了一个简单的 WebSocket 服务,能够在 Vue 应用中进行实时通信。WebSocket 的全双工通信特性使得我们能够高效地处理实时数据,而封装好的 WebSocketService 类则使得代码更加模块化和易于维护。

无论是聊天应用、实时通知还是在线游戏,WebSocket 都是实现实时交互的重要工具。希望本文能帮助你更好地理解和使用 WebSocket。在实际开发中,可以根据具体需求扩展和优化这个基础实现。

相关文章:

前端WebSocket应用——聊天实时通信的基本配置

使用 WebSocket 实现实时通信的 Vue 应用 前言1. WebSocketService 类 1.1 类属性1.2 构造函数和连接初始化1.3 WebSocket 连接1.4 事件处理方法1.5 发送和关闭 WebSocket 消息1.6 状态查询与回调注册1.7 完整代码 2. 在 Vue 组件中使用 WebSocketService 2.1 定义 WebSocket …...

博弈论1:拿走游戏(take-away game)

假设你和小红打赌,玩“拿走游戏”,输的人请对方吃饭.... 你们面前有21个筹码,放成一堆;每轮你或者小红可以从筹码堆中拿走1个/2个/3个;第一轮你先拿,第二轮小红拿,你们两个人交替进行;拿走筹码堆…...

Debezium OracleValueConverters 分析

Debezium OracleValueConverters 分析 目录 1. 概述2. 核心功能3. 数据类型映射4. 特殊场景处理5. 最佳实践6. 使用示例7. 常见问题8. 扩展建议9. 总结1. 概述 OracleValueConverters 是 Debezium Oracle 连接器中负责数据类型转换的核心类,它继承自 JdbcValueConverters。主…...

WPF 消息循环(二)

们已经知道,win32/MFC/WinForm/WPF 都依靠消息循环驱动,让程序跑起来。 这里就介绍 WPF 中是如何使用消息循环来驱动程序的。 1. 背景 只听说过 Dispatcher ,哪里来的消息循环? WPF 启动运行堆栈: > WpfApp1.…...

ubuntu上更改ext4格式的硬盘为 windows的 NTFS 格式参考

1. ubuntu上安装 sudo apt-get install gparted 2. 参考如下,下面是转换后的样例。 3.windows上添加识别新硬盘参考 先在设备管理器中 找到下面 磁盘管理 如下:找到类似下面的磁盘2 查看相关信息 右键可以新建卷和格式化,下面是已经新建…...

Fastapi教程:使用 aioredis 连接池执行Redis 的高效异步操作

在构建高性能的 Web 应用时,缓存系统是一个至关重要的组成部分。Redis 是最常见的缓存系统之一,它提供了高效的存储与读取机制。然而,在与 Redis 进行频繁交互时,创建和销毁连接可能会成为瓶颈。为了优化这一问题,我们…...

配置mysqld(读取选项内容,基本配置),数据目录(配置的必要性,目录下的内容,具体文件介绍,修改配置)

目录 配置mysqld 读取选项内容 介绍 启动脚本 基本配置 内容 端口号 数据目录的路径 配置的必要性 配置路径 mysql数据目录 具体文件 修改配置时 权限问题 配置mysqld 读取选项内容 介绍 会从[mysqld] / [server] 节点中读取选项内容 优先读取[server] 虽然服务…...

docker 容器相互访问

目前采用 network 方式 1. 创建自定义网络 docker network create network-group 如下 2. 相互访问的容器更改(目前演示redis 以及netcore api 访问redis ) //redis 原有容器删除 跟之前区别就是加入 --network network-group docker run \ -p 6379:…...

算法1(蓝桥杯18)-删除链表的倒数第 N 个节点

问题: 给你一个链表,删除链表的倒数第 n 个节点,并且返回链表的头节点。 输入:head 1 -> 2 -> 3 -> 4 -> 5 -> null, n 2 输出:1 -> 2 -> 3 -> 5 -> null输入:head 1 ->…...

【PyTorch】动态调整学习率 torch.optim.lr_scheduler.StepLR 调度器

文章目录 1. torch.optim.lr_scheduler.StepLR 官方文档详解2. 使用示例2.1 官方提供使用示例2.2 自己写代码测试方法2.2.1 get_last_lr() 方法2.2.2 state_dict() 方法2.2.3 load_state_dict() 保存和加载调度器 3. 思考3.1 为什么需要state_dict()3.2 get_lr() 与 get_last_l…...

AIGC drug design 人工智能生成式药物设计:基于 GPT 的 SMILES 生成与应用

人工智能生成式药物设计:基于 GPT 的 SMILES 生成与应用 1. 人工智能生成模型:解密 GPT 的工作原理 目录 引言 1.1 背景介绍 1.2 人工智能生成模型的兴起 1.3 GPT 系列模型的地位与影响 GPT 模型概述 2.1 什么是 GPT 2.2 GPT 的发展历程 2.3 GPT 与其…...

Python面试常见问题及答案4

一、内存管理相关 问题:Python中的垃圾回收机制是如何工作的? 答案:Python主要使用引用计数来进行垃圾回收,当对象的引用计数为0时,该对象就会被垃圾回收器回收。此外,Python还有一个循环垃圾收集器来处理循…...

开启第二阶段---蓝桥杯

一、12.10--数据类型的范围及转化 今天是刚开始,一天一道题 对于这道题我想要记录的是Java中的整数默认是 int 类型,如果数值超出了 int 的范围,就会发生溢出错误。为了避免这个问题,可以将数字表示为 long 类型,方法…...

npm内存溢出

项目过大运行项目内存溢出 报错代码 运行内存溢出 increase-memory-limit ‘“node --max-old-space-size8192”’ 不是内部或外部命令,也不是可运行的程序 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of m…...

回归预测 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多输入单输出回归预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 CNN-BiGRU,即卷积神经网络(CNN)与双…...

Android系统卡启动问题排查

Android系统启动正常来说会涉及到如下几个过程: 引导加载程序(Bootloader)Linux内核(Kernel),负责硬件抽象、内存管理、进程管理、网络堆栈等init进程 init进程读取init.rc配置文件,用于启动各…...

STP(生成树协议)

STP的基本概念 概述 STP是一个用于局域网中消除环路的协议。运行该协议的设备通过彼此交互信息而发现网络中的环路,并对某些接口进行阻塞以消除环路。STP在网络中运行后会持续监控网络的状态,当网络出现拓扑变更时,STP能够感知并且进行自动…...

【前端面试】随机、结构赋值、博弈题

解构赋值(Destructuring Assignment)是 JavaScript ES6 引入的一项非常有用的特性,它允许我们快速地从数组或对象中提取值,并将它们赋给变量。这种方式使得代码更加简洁、易读,并且能够减少重复的访问和赋值操作。 1.…...

Volta——开箱即用的Node.js 版本管理工具

Volta volta 是一个较新的 Node.js 版本管理器,旨在简化 Node.js 和其他工具的安装和管理,在 2019 年出世,仍在积极开发中。Volta 采用了与 nvm 不同的方法:它不是管理 Node.js 的多个版本,而是管理项目及其依赖项。当…...

ubuntu 磁盘空间满,找不到占用文件的目录

解决方法: 检查磁盘空间: 执行 df -h 查看各分区磁盘使用情况。 查找大文件或目录: 执行 du -sh /* 2>/dev/null 查找根目录下的大文件或目录,再逐一进入子目录使用相同命令查找。 清理缓存和临时文件: 清理 /t…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...