使用 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 組件中,我們可以利用 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.");
});
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。在實際開發中,可以根據具體需求擴展和優化這個基礎實現。