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

使用 WebSocket 实现实时通信的 Vue 应用
  • 前言
  • [1. WebSocketService 类](#1. WebSocketService 类)
    • [1.1 类属性](#1.1 类属性)
    • [1.2 构造函数和连接初始化](#1.2 构造函数和连接初始化)
    • [1.3 WebSocket 连接](#1.3 WebSocket 连接)
    • [1.4 事件处理方法](#1.4 事件处理方法)
    • [1.5 发送和关闭 WebSocket 消息](#1.5 发送和关闭 WebSocket 消息)
    • [1.6 状态查询与回调注册](#1.6 状态查询与回调注册)
    • [1.7 完整代码](#1.7 完整代码)
  • [2. 在 Vue 组件中使用 WebSocketService](#2. 在 Vue 组件中使用 WebSocketService)
    • [2.1 定义 WebSocket URL](#2.1 定义 WebSocket URL)
    • [2.2 实例化 WebSocketService](#2.2 实例化 WebSocketService)
    • [2.3 生命周期钩子](#2.3 生命周期钩子)
  • [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。在实际开发中,可以根据具体需求扩展和优化这个基础实现。

相关推荐
布列瑟农的星空2 分钟前
大话设计模式——关注点分离原则下的事件处理
前端·后端·架构
yvvvy21 分钟前
前端必懂的 Cache 缓存机制详解
前端
北海几经夏36 分钟前
React自定义Hook
前端·react.js
龙在天41 分钟前
从代码到屏幕,浏览器渲染网页做了什么❓
前端
TimelessHaze42 分钟前
【performance面试考点】让面试官眼前一亮的performance性能优化
前端·性能优化·trae
yes or ok1 小时前
前端工程师面试题-vue
前端·javascript·vue.js
我要成为前端高手1 小时前
给不支持摇树的三方库(phaser) tree-shake?
前端·javascript
Noxi_lumors1 小时前
VITE BALABALA require balabla not supported
前端·vite
周胜21 小时前
node-sass
前端
aloha_2 小时前
Windows 系统中,杀死占用某个端口(如 8080)的进程
前端