1.0.3 的相关功能
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import mittBus from './mittBus'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
|
||||
type JsonValue = Record<string, any> | any[]
|
||||
|
||||
const WS_BASE = 'wss://mzl.dev.hnxinyouhe.com/ws?token='
|
||||
|
||||
let socket: WebSocket | null = null
|
||||
let reconnectTimer: any = null
|
||||
let heartbeatTimer: any = null
|
||||
let reconnectAttempts = 0
|
||||
const maxReconnectDelayMs = 30000
|
||||
const heartbeatIntervalMs = 30000
|
||||
|
||||
const getReconnectDelay = () => {
|
||||
const base = 1000 * Math.pow(2, reconnectAttempts)
|
||||
return Math.min(base, maxReconnectDelayMs)
|
||||
}
|
||||
|
||||
const cleanup = () => {
|
||||
if (reconnectTimer) {
|
||||
clearTimeout(reconnectTimer)
|
||||
reconnectTimer = null
|
||||
}
|
||||
if (heartbeatTimer) {
|
||||
clearTimeout(heartbeatTimer)
|
||||
heartbeatTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
const startHeartbeat = () => {
|
||||
// 清理上一次的心跳
|
||||
if (heartbeatTimer) {
|
||||
clearTimeout(heartbeatTimer)
|
||||
heartbeatTimer = null
|
||||
}
|
||||
// 递归 setTimeout,确保固定间隔执行
|
||||
heartbeatTimer = setTimeout(() => {
|
||||
try {
|
||||
if (socket && socket.readyState === WebSocket.OPEN) {
|
||||
socket.send(JSON.stringify({ type: 'ping' }))
|
||||
}
|
||||
} catch (_) {}
|
||||
// 下一次心跳
|
||||
startHeartbeat()
|
||||
}, heartbeatIntervalMs)
|
||||
}
|
||||
|
||||
const scheduleReconnect = () => {
|
||||
cleanup()
|
||||
const delay = getReconnectDelay()
|
||||
reconnectTimer = setTimeout(() => {
|
||||
const { accessToken } = useUserStore()
|
||||
if (accessToken) initWebSocket(accessToken)
|
||||
}, delay)
|
||||
}
|
||||
|
||||
export const initWebSocket = (token: string) => {
|
||||
try {
|
||||
if (!token) return
|
||||
if (socket) {
|
||||
try {
|
||||
socket.close()
|
||||
} catch (_) {}
|
||||
socket = null
|
||||
}
|
||||
cleanup()
|
||||
|
||||
const url = `${WS_BASE}${token}`
|
||||
socket = new WebSocket(url)
|
||||
|
||||
socket.onopen = () => {
|
||||
reconnectAttempts = 0
|
||||
startHeartbeat()
|
||||
mittBus.emit('ws:open')
|
||||
try {
|
||||
socket?.send(JSON.stringify({ type: 'ping' }))
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
socket.onmessage = (event) => {
|
||||
const dataStr = event.data
|
||||
let data: any = dataStr
|
||||
try {
|
||||
data = JSON.parse(dataStr)
|
||||
} catch (_) {}
|
||||
mittBus.emit('ws:message', data)
|
||||
}
|
||||
|
||||
socket.onerror = (err) => {
|
||||
mittBus.emit('ws:error', err)
|
||||
}
|
||||
|
||||
socket.onclose = () => {
|
||||
mittBus.emit('ws:close')
|
||||
reconnectAttempts += 1
|
||||
scheduleReconnect()
|
||||
}
|
||||
} catch (e) {
|
||||
mittBus.emit('ws:error', e)
|
||||
scheduleReconnect()
|
||||
}
|
||||
}
|
||||
|
||||
export const closeWebSocket = () => {
|
||||
cleanup()
|
||||
try {
|
||||
socket?.close()
|
||||
} catch (_) {}
|
||||
socket = null
|
||||
}
|
||||
|
||||
export const sendWebSocket = (payload: string | JsonValue) => {
|
||||
if (!socket || socket.readyState !== WebSocket.OPEN) return false
|
||||
try {
|
||||
const data = typeof payload === 'string' ? payload : JSON.stringify(payload)
|
||||
socket.send(data)
|
||||
return true
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user