This commit is contained in:
oneao committed 2025-10-13 17:33:35 +08:00
1 parent 2598098876
commit db2208cc92
1 file changed
+75 -13
@@ -6,8 +6,19 @@ export function useWebSocket() {
const isConnected = ref(false) const isConnected = ref(false)
const listeners = ref(new Set()) const listeners = ref(new Set())
// 定时器
let pingInterval, pongTimeout, connectTimeout
// 重连状态
let reconnecting = false let reconnecting = false
let reconnectNotification = null let reconnectNotification = null
let reconnectDelay = 3000
// 常量
const MAX_RECONNECT_DELAY = 30000
const PING_INTERVAL = 5000
const PONG_TIMEOUT = 10000
const CONNECT_TIMEOUT = 3000
function connect(url) { function connect(url) {
if (isConnected.value) if (isConnected.value)
@@ -18,15 +29,20 @@ export function useWebSocket() {
const ws = new WebSocket(url) const ws = new WebSocket(url)
socket.value = ws socket.value = ws
// 连接超时
connectTimeout = setTimeout(() => !isConnected.value && ws.close(), CONNECT_TIMEOUT)
ws.onopen = () => { ws.onopen = () => {
clearTimeout(connectTimeout)
isConnected.value = true isConnected.value = true
reconnecting = false reconnecting = false
// 关闭重连提示 reconnectDelay = 3000
if (reconnectNotification) { startHeartbeat()
reconnectNotification.close()
reconnectNotification = null // 关闭重连通知
} reconnectNotification?.close()
console.log('WebSocket 已连接') reconnectNotification = null
ElNotification({ ElNotification({
title: '成功', title: '成功',
message: 'WebSocket 已连接', message: 'WebSocket 已连接',
@@ -34,11 +50,14 @@ export function useWebSocket() {
showClose: false, showClose: false,
duration: 2000, duration: 2000,
}) })
console.log('WebSocket 已连接')
} }
ws.onmessage = (event) => { ws.onmessage = (event) => {
try { try {
const message = JSON.parse(event.data) const message = JSON.parse(event.data)
if (message.type === 'PONG')
return resetPongTimeout()
notifyListeners(message) notifyListeners(message)
} }
catch (err) { catch (err) {
@@ -47,13 +66,22 @@ export function useWebSocket() {
} }
} }
ws.onclose = () => scheduleReconnect(url) ws.onclose = (event) => {
ws.onerror = () => scheduleReconnect(url) handleDisconnect()
if (event.code !== 1000)
scheduleReconnect(url)
}
ws.onerror = (err) => {
console.error('WebSocket错误:', err)
handleDisconnect()
scheduleReconnect(url)
}
} }
function disconnect() { function disconnect() {
socket.value?.close() socket.value?.close()
isConnected.value = false cleanup()
} }
function sendMessage(type, data) { function sendMessage(type, data) {
@@ -71,9 +99,34 @@ export function useWebSocket() {
listeners.value.forEach(cb => cb(message)) listeners.value.forEach(cb => cb(message))
} }
function startHeartbeat() {
pingInterval = setInterval(() => {
if (socket.value?.readyState === WebSocket.OPEN) {
sendMessage('PING')
pongTimeout = setTimeout(() => {
console.warn('未收到PONG,关闭WebSocket')
socket.value?.close()
}, PONG_TIMEOUT)
}
}, PING_INTERVAL)
}
function resetPongTimeout() {
clearTimeout(pongTimeout)
}
function handleDisconnect() {
isConnected.value = false
cleanup()
}
function scheduleReconnect(url) { function scheduleReconnect(url) {
if (!reconnecting) { if (reconnecting)
reconnecting = true return
reconnecting = true
// 显示一次重连提示
if (!reconnectNotification) {
reconnectNotification = ElNotification({ reconnectNotification = ElNotification({
title: '提示', title: '提示',
message: 'WebSocket 连接断开,正在重连...', message: 'WebSocket 连接断开,正在重连...',
@@ -82,10 +135,19 @@ export function useWebSocket() {
duration: 0, duration: 0,
}) })
} }
console.log('WebSocket 即将重连...')
console.log(`WebSocket将在${reconnectDelay / 1000}s后尝试重连`)
setTimeout(() => { setTimeout(() => {
connect(url) connect(url)
}, 3000) // 固定延迟重连,可按需改 reconnectDelay = Math.min(reconnectDelay * 2, MAX_RECONNECT_DELAY)
reconnecting = false
}, reconnectDelay)
}
function cleanup() {
clearInterval(pingInterval)
clearTimeout(pongTimeout)
clearTimeout(connectTimeout)
} }
onScopeDispose(() => disconnect()) onScopeDispose(() => disconnect())