From 238ddbbe563e9c3313c4717b307e0cd2b3cd74ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 27 Oct 2026 11:23:07 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=90=8C=E6=AD=A5=20WebSocket=20ping/po?= =?UTF-8?q?ng=20=E5=BF=83=E8=B7=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/push.ts | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/utils/push.ts b/src/utils/push.ts index efb53447..0d94de85 100644 --- a/src/utils/push.ts +++ b/src/utils/push.ts @@ -12,6 +12,8 @@ import { parsePushMessage, resolveNoticeGroup, resolveNoticeTitle, shouldAppendN let eventSource: EventSource | undefined; let webSocket: WebSocket | undefined; let reconnectTimer: number | undefined; +let heartbeatTimer: number | undefined; +let pongTimer: number | undefined; let reconnectAttempts = 0; let pushClosed = true; const KICKED_MESSAGE = 'kicked'; @@ -103,6 +105,13 @@ function clearReconnectTimer() { } } +function clearHeartbeatTimers() { + if (heartbeatTimer) window.clearInterval(heartbeatTimer); + if (pongTimer) window.clearTimeout(pongTimer); + heartbeatTimer = undefined; + pongTimer = undefined; +} + function scheduleReconnect(connect: () => void, maxRetries: number, delay: number) { if (pushClosed) return; if (reconnectAttempts >= maxRetries) return; @@ -133,16 +142,30 @@ function initSsePush(path: string) { function initWsPush(path: string) { const connect = () => { if (pushClosed) return; + clearHeartbeatTimers(); webSocket?.close(); - webSocket = new WebSocket(buildWsUrl(path)); - webSocket.onopen = () => { + const socket = new WebSocket(buildWsUrl(path)); + webSocket = socket; + socket.onopen = () => { reconnectAttempts = 0; + heartbeatTimer = window.setInterval(() => { + if (socket.readyState !== WebSocket.OPEN) return; + socket.send('ping'); + pongTimer = window.setTimeout(() => socket.close(), 2000); + }, 10000); }; - webSocket.onmessage = event => { - if (String(event.data) === 'pong') return; + socket.onmessage = event => { + if (String(event.data) === 'pong') { + if (pongTimer) window.clearTimeout(pongTimer); + pongTimer = undefined; + return; + } handlePushMessage(String(event.data)); }; - webSocket.onclose = () => scheduleReconnect(connect, 3, 1000); + socket.onclose = () => { + clearHeartbeatTimers(); + scheduleReconnect(connect, 3, 1000); + }; }; connect(); } @@ -177,6 +200,7 @@ export function initPush() { export function closePush() { pushClosed = true; clearReconnectTimer(); + clearHeartbeatTimers(); if (webSocket) { webSocket.onopen = null; webSocket.onmessage = null;