WebSocket 前端實作筆記 🚀
專案背景
前端技術棧:Vue3
組員:「欸!為什麼要寫一個 websocket.js?」
開發的時候養成好習慣超重要!(我覺得我很棒)
與其在每個需要用到 WebSocket 的地方都重新寫一次邏輯, 不如把它包成一個服務類別,這樣哪裡要用就 import 進來用就好啦~
類別怎麼設計的 🤔
首先會需要三個重要的屬性:
constructor() {
this.ws = null // WebSocket 連接實例
this.isConnected = false // 追蹤連接狀態
this.messageHandlers = new Map() // 用來存放各種消息的處理函數
}
為什麼要用 Map 來存處理函數? 因為超級方便的啊!比如說:
想處理 「加入購物車」 的消息? → 存一個 handler 進 Map
想處理 「移除商品」 的消息? → 再存一個 handler
收到消息時查一下 Map 就知道要用哪個 handler 了
比寫一堆 if-else 來得清爽多了!
重要的方法們 👾
connect() - 建立連接
connect() {
// 建立 WebSocket 連接
this.ws = new WebSocket(`${import.meta.env.VITE_WEBSOCKET_URL}`)
// 連接成功
this.ws.onopen = () => {
this.isConnected = true
console.log('耶~連上了!')
}
// 收到消息
this.ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data)
const handler = this.messageHandlers.get(data.type)
if (handler) {
handler(data)
} else {
console.warn(`咦?沒有處理 ${data.type} 的函數耶`)
}
} catch (error) {
console.error("哎呀!解析消息失敗了:", error)
}
}
// 斷開連接
this.ws.onclose = () => {
this.isConnected = false
console.log('斷線了QQ')
}
// 連接出錯
this.ws.onerror = (error) => {
console.error("糟糕!連接出錯了:", error)
this.isConnected = false
}
}
onMessage() - 註冊消息處理函數
onMessage(type, handler) {
// 簡單!把處理函數存進 Map
this.messageHandlers.set(type, handler)
}
sendMessage() - 發送消息
sendMessage(type, data) {
// 檢查一下連接狀態
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
console.error("欸欸!還沒連上不能發送啦")
return
}
try {
const message = JSON.stringify({ type, data })
this.ws.send(message)
} catch (error) {
console.error("糟糕!發送失敗了:", error)
}
}
disconnect() - 斷開連接
disconnect() {
if (this.ws) {
this.ws.close()
this.ws = null
this.isConnected = false
}
}
怎麼讓整個專案都用同一個 WebSocket?
用單例模式!就是把這個服務包成一個實例然後導出:
export const webSocketService = new WebSocketService()
這樣在其他地方要用的時候就:
import { webSocketService } from './websocket'
搞定!整個專案都會用到同一個 WebSocket 實例,超方便的~
之後可以加強的地方 💪
加個重連機制:斷線自動重連
加個心跳檢測:確保連接還活著
處理離線時的消息:可以先存起來等連上再發
錯誤重試:發送失敗自動重試幾次
好啦!這樣就完成了一個基本的 WebSocket 服務類別,之後在共享購物車頁面就可以直接 import 來用~ 🎉
Last updated