From 4f31cbf938a245631c47691fd1674d7b39d74e2a Mon Sep 17 00:00:00 2001 From: goodjun Date: Fri, 26 Apr 2024 21:33:30 +0800 Subject: [PATCH 1/3] feat: add max attempt callback --- packages/hooks/src/useWebSocket/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/hooks/src/useWebSocket/index.ts b/packages/hooks/src/useWebSocket/index.ts index 8260195133..9f64c23b96 100644 --- a/packages/hooks/src/useWebSocket/index.ts +++ b/packages/hooks/src/useWebSocket/index.ts @@ -18,6 +18,7 @@ export interface Options { onClose?: (event: WebSocketEventMap['close'], instance: WebSocket) => void; onMessage?: (message: WebSocketEventMap['message'], instance: WebSocket) => void; onError?: (event: WebSocketEventMap['error'], instance: WebSocket) => void; + onMaxAttempt?: () => void; protocols?: string | string[]; } @@ -40,6 +41,7 @@ export default function useWebSocket(socketUrl: string, options: Options = {}): onClose, onMessage, onError, + onMaxAttempt, protocols, } = options; @@ -47,6 +49,7 @@ export default function useWebSocket(socketUrl: string, options: Options = {}): const onCloseRef = useLatest(onClose); const onMessageRef = useLatest(onMessage); const onErrorRef = useLatest(onError); + const onMaxAttemptRef = useLatest(onMaxAttempt); const reconnectTimesRef = useRef(0); const reconnectTimerRef = useRef>(); From 7f46b977d7ffc0bf7f829f9de3779b371e17b4c8 Mon Sep 17 00:00:00 2001 From: goodjun Date: Sat, 27 Apr 2024 23:58:53 +0800 Subject: [PATCH 2/3] feat(useWebSocket): add max attempt callback --- .../src/useWebSocket/__tests__/index.test.ts | 49 +++++++++++++++++++ packages/hooks/src/useWebSocket/index.ts | 13 +++++ 2 files changed, 62 insertions(+) diff --git a/packages/hooks/src/useWebSocket/__tests__/index.test.ts b/packages/hooks/src/useWebSocket/__tests__/index.test.ts index ad6949577b..4bdc771c5e 100644 --- a/packages/hooks/src/useWebSocket/__tests__/index.test.ts +++ b/packages/hooks/src/useWebSocket/__tests__/index.test.ts @@ -145,3 +145,52 @@ describe('useWebSocket', () => { act(() => wsServer2.close()); }); }); + +it('should call onMaxAttempt when reconnect attempts exceeded and unable to connect to server', async () => { + const onMaxAttempt = jest.fn(); + + renderHook(() => + useWebSocket('ws://localhost:8888', { + onMaxAttempt, + reconnectInterval: 100, + }), + ); + + await act(async () => { + await sleep(500); + }); + + expect(onMaxAttempt).toBeCalledTimes(1); +}); + +it('should call onMaxAttempt when reconnect attempts exceed and server disconnects', async () => { + const onMaxAttempt = jest.fn(); + + const wsServer = new WS(wsUrl); + + renderHook(() => + useWebSocket(wsUrl, { + onMaxAttempt, + reconnectInterval: 100, + reconnectLimit: 1, + }), + ); + + await act(async () => { + await wsServer.connected; + }); + + wsServer.close(); + + await act(async () => { + await wsServer.connected; + }); + + wsServer.close(); + + await act(async () => { + await sleep(500); + }); + + expect(onMaxAttempt).toBeCalledTimes(1); +}); diff --git a/packages/hooks/src/useWebSocket/index.ts b/packages/hooks/src/useWebSocket/index.ts index 9f64c23b96..e4f709ae42 100644 --- a/packages/hooks/src/useWebSocket/index.ts +++ b/packages/hooks/src/useWebSocket/index.ts @@ -54,6 +54,7 @@ export default function useWebSocket(socketUrl: string, options: Options = {}): const reconnectTimesRef = useRef(0); const reconnectTimerRef = useRef>(); const websocketRef = useRef(); + const maxAttemptThrottle = useRef>(); const [latestMessage, setLatestMessage] = useState(); const [readyState, setReadyState] = useState(ReadyState.Closed); @@ -72,6 +73,14 @@ export default function useWebSocket(socketUrl: string, options: Options = {}): connectWs(); reconnectTimesRef.current++; }, reconnectInterval); + } else { + if (maxAttemptThrottle.current) { + clearTimeout(maxAttemptThrottle.current); + } + + maxAttemptThrottle.current = setTimeout(() => { + onMaxAttemptRef.current?.(); + }, 100); } }; @@ -143,6 +152,10 @@ export default function useWebSocket(socketUrl: string, options: Options = {}): clearTimeout(reconnectTimerRef.current); } + if (maxAttemptThrottle.current) { + clearTimeout(maxAttemptThrottle.current); + } + reconnectTimesRef.current = reconnectLimit; websocketRef.current?.close(); websocketRef.current = undefined; From 40b6a07213beb5a3ed4b689b8b227a2837a762d8 Mon Sep 17 00:00:00 2001 From: goodjun Date: Sat, 27 Apr 2024 23:59:14 +0800 Subject: [PATCH 3/3] docs(useWebSocket): update doc --- packages/hooks/src/useWebSocket/index.en-US.md | 1 + packages/hooks/src/useWebSocket/index.zh-CN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/hooks/src/useWebSocket/index.en-US.md b/packages/hooks/src/useWebSocket/index.en-US.md index 763a18681e..b8eddbb70e 100644 --- a/packages/hooks/src/useWebSocket/index.en-US.md +++ b/packages/hooks/src/useWebSocket/index.en-US.md @@ -60,6 +60,7 @@ useWebSocket(socketUrl: string, options?: Options): Result; | onClose | WebSocket close callback | `(event: WebSocketEventMap['close'], instance: WebSocket) => void` | - | | onMessage | WebSocket receive message callback | `(message: WebSocketEventMap['message'], instance: WebSocket) => void` | - | | onError | WebSocket error callback | `(event: WebSocketEventMap['error'], instance: WebSocket) => void` | - | +| onMaxAttempt | Reconnect attempts exceed callback | `() => void` | - | | reconnectLimit | Retry times | `number` | `3` | | reconnectInterval | Retry interval(ms) | `number` | `3000` | | manual | Manually starts connection | `boolean` | `false` | diff --git a/packages/hooks/src/useWebSocket/index.zh-CN.md b/packages/hooks/src/useWebSocket/index.zh-CN.md index 4d7f52a84d..9d06dac6fa 100644 --- a/packages/hooks/src/useWebSocket/index.zh-CN.md +++ b/packages/hooks/src/useWebSocket/index.zh-CN.md @@ -60,6 +60,7 @@ useWebSocket(socketUrl: string, options?: Options): Result; | onClose | webSocket 关闭回调 | `(event: WebSocketEventMap['close'], instance: WebSocket) => void` | - | | onMessage | webSocket 收到消息回调 | `(message: WebSocketEventMap['message'], instance: WebSocket) => void` | - | | onError | webSocket 错误回调 | `(event: WebSocketEventMap['error'], instance: WebSocket) => void` | - | +| onMaxAttempt | 重试最大次数回调 | `() => void` | - | | reconnectLimit | 重试次数 | `number` | `3` | | reconnectInterval | 重试时间间隔(ms) | `number` | `3000` | | manual | 手动启动连接 | `boolean` | `false` |