在现代 Web 应用中,实时通信是提升用户体验的重要因素之一。WebSocket 协议提供了一种在客户端和服务器之间建立持久连接的方式,使得双向数据传输成为可能。本文将通过两个代码段,展示如何在 Vue 应用中使用 WebSocket 实现实时消息接收和发送。
首先,我们定义一个 WebSocketService
类,用于管理 WebSocket 连接及其相关操作。以下是该类的实现:
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; // 消息回调函数
constructor(socketUrl: string) {
const userStore = useUserStore();
this.token = userStore.token;
this.connect(socketUrl);
}
connect(socketUrl) 方法创建一个新的 WebSocket 实例,传入 socketUrl 和 this.token 作为子协议,用于与服务器通信。
为 WebSocket 注册了以下事件监听器:
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);
});
}
onOpen(event: Event): 在 WebSocket 连接成功后触发。
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 接收到消息时触发。
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 连接关闭时触发。
private onClose(event: CloseEvent) {
console.log("WebSocket closed:", event);
this.isConnected = false;
}
sendMessage(message: string): 用于发送消息到服务器。
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();
}
}
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;
}
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;
在 Vue 组件中,我们可以利用 onMounted
和 onBeforeUnmount
生命周期钩子来管理 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.");
});
const websocketService = new WebSocketService(socketUrl); 这一行创建了 WebSocketService 类的一个实例,并将之前定义的 socketUrl 作为参数传递给构造函数。
close
方法关闭 WebSocket 连接,以释放资源。通过上述代码,我们实现了一个简单的 WebSocket 服务,能够在 Vue 应用中进行实时通信。WebSocket 的全双工通信特性使得我们能够高效地处理实时数据,而封装好的 WebSocketService
类则使得代码更加模块化和易于维护。
无论是聊天应用、实时通知还是在线游戏,WebSocket 都是实现实时交互的重要工具。希望本文能帮助你更好地理解和使用 WebSocket。在实际开发中,可以根据具体需求扩展和优化这个基础实现。