u
This commit is contained in:
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())
|
||||||
|
|||||||
Reference in new issue
Block a user