功能:
自动重连(断开自动重连)
心跳保活(防止服务器踢下线)
消息重发(发送失败重试)
错误统一处理
在线 / 离线监听
消息订阅 / 派发(解耦)
可重入、单例模式
javascript
class WebSocketClient {
constructor(url) {
// 基础配置
this.url = url
this.socket = null
this.isConnected = false
// 重连配置
this.reconnectEnabled = true // 自动重连开关
this.reconnectDelay = 3000 // 重连间隔 3s
this.reconnectTimer = null // 重连定时器
// 心跳配置(防止服务器断开)
this.heartbeatEnabled = true
this.heartbeatMsg = 'ping' // 心跳消息
this.heartbeatInterval = 5000 // 5秒一次心跳
this.heartbeatTimer = null
// 消息订阅器(不同页面接收不同消息)
this.listeners = new Map()
// 缓存未发送成功的消息
this.msgQueue = []
}
// ========== 1. 建立连接 ==========
connect() {
// 防止重复创建
if (this.socket && this.socket.readyState === 1) return
this.socket = new WebSocket(this.url)
// 连接成功
this.socket.onopen = (e) => {
console.log('✅ WebSocket 连接成功')
this.isConnected = true
this.startHeartbeat() // 启动心跳
this.clearReconnect() // 清除重连
this.sendCacheMsg() // 发送缓存消息
}
// 接收消息
this.socket.onmessage = (e) => {
try {
const data = JSON.parse(e.data)
this.dispatch(data) // 分发给订阅者
} catch (err) {
this.dispatch(e.data)
}
}
// 关闭连接
this.socket.onclose = (e) => {
console.log('❌ WebSocket 断开')
this.isConnected = false
this.stopHeartbeat()
this.reconnect() // 自动重连
}
// 错误
this.socket.onerror = (err) => {
console.error('❗ WebSocket 异常', err)
this.isConnected = false
this.reconnect()
}
}
// ========== 2. 自动重连 ==========
reconnect() {
if (!this.reconnectEnabled || this.reconnectTimer) return
console.log(`🔄 ${this.reconnectDelay / 1000}秒后重连...`)
this.reconnectTimer = setTimeout(() => {
this.connect()
this.reconnectTimer = null
}, this.reconnectDelay)
}
clearReconnect() {
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer)
this.reconnectTimer = null
}
}
// ========== 3. 心跳保活(最重要!) ==========
startHeartbeat() {
if (!this.heartbeatEnabled) return
this.stopHeartbeat()
this.heartbeatTimer = setInterval(() => {
if (this.isConnected) {
this.send(this.heartbeatMsg)
}
}, this.heartbeatInterval)
}
stopHeartbeat() {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer)
this.heartbeatTimer = null
}
}
// ========== 4. 发送消息(支持缓存) ==========
send(data) {
if (!this.isConnected) {
this.msgQueue.push(data) // 未连接 → 缓存
return
}
try {
const msg = typeof data === 'string' ? data : JSON.stringify(data)
this.socket.send(msg)
} catch (err) {
console.error('发送失败', err)
this.msgQueue.push(data)
}
}
// 发送缓存消息
sendCacheMsg() {
while (this.msgQueue.length) {
const msg = this.msgQueue.shift()
this.send(msg)
}
}
// ========== 5. 订阅/派发(解耦) ==========
on(key, callback) {
this.listeners.set(key, callback)
}
off(key) {
this.listeners.delete(key)
}
dispatch(data) {
this.listeners.forEach((cb) => cb(data))
}
// ========== 6. 手动关闭 ==========
close() {
this.reconnectEnabled = false // 关闭重连
this.stopHeartbeat()
this.clearReconnect()
this.socket?.close()
this.isConnected = false
}
}
// 导出单例
export default new WebSocketClient('ws://localhost:8080/ws')
使用
javascript
import ws from '@/utils/websocket'
// 1. 连接
ws.connect()
// 2. 监听消息
ws.on('message', (data) => {
console.log('收到服务器消息:', data)
})
// 3. 发送消息
ws.send({ type: 'chat', content: '你好' })
// 4. 页面卸载关闭
onUnmounted(() => {
ws.off('message')
})