|
|
@@ -11,13 +11,14 @@ export enum ReadyState {
|
|
|
}
|
|
|
|
|
|
export interface Options {
|
|
|
- reconnectLimit?: number;
|
|
|
- reconnectInterval?: number;
|
|
|
+ // reconnectLimit?: number;
|
|
|
+ // reconnectInterval?: number;
|
|
|
manual?: boolean;
|
|
|
onOpen?: (event: WebSocketEventMap['open']) => void;
|
|
|
onClose?: (event: WebSocketEventMap['close']) => void;
|
|
|
onMessage?: (message: WebSocketEventMap['message']) => void;
|
|
|
onError?: (event: WebSocketEventMap['error']) => void;
|
|
|
+ onReconnect?: () => void;
|
|
|
}
|
|
|
|
|
|
export interface Result {
|
|
|
@@ -31,18 +32,21 @@ export interface Result {
|
|
|
|
|
|
export default function useWebSocket(socketUrl: string, options: Options = {}): Result {
|
|
|
const {
|
|
|
- reconnectLimit = 3,
|
|
|
- reconnectInterval = 3 * 1000,
|
|
|
+ // reconnectLimit = 3,
|
|
|
+ // reconnectInterval = 3 * 1000,
|
|
|
manual = false,
|
|
|
onOpen,
|
|
|
onClose,
|
|
|
onMessage,
|
|
|
+ onReconnect,
|
|
|
onError,
|
|
|
} = options;
|
|
|
|
|
|
- const reconnectTimesRef = useRef(0);
|
|
|
- const reconnectTimerRef = useRef<NodeJS.Timeout>();
|
|
|
+ const reconnectTimesRef = useRef(0); // 重连次数
|
|
|
+ const reconnectTimerRef = useRef<NodeJS.Timeout>(); // 计时器
|
|
|
const websocketRef = useRef<WebSocket>();
|
|
|
+ const lockReconnect = useRef(false); // 避免重复连接
|
|
|
+ const isReconnect = useRef(false);
|
|
|
|
|
|
const [latestMessage, setLatestMessage] = useState<WebSocketEventMap['message']>();
|
|
|
const [readyState, setReadyState] = useState<ReadyState>(ReadyState.Closed);
|
|
|
@@ -52,7 +56,7 @@ export default function useWebSocket(socketUrl: string, options: Options = {}):
|
|
|
if (ws) {
|
|
|
setReadyState(ws?.readyState);
|
|
|
} else {
|
|
|
- if (reconnectTimerRef.current) clearTimeout(reconnectTimerRef.current);
|
|
|
+ // if (reconnectTimerRef.current) clearTimeout(reconnectTimerRef.current);
|
|
|
|
|
|
// if (websocketRef.current) {
|
|
|
// // 此处应考虑状态。
|
|
|
@@ -60,16 +64,21 @@ export default function useWebSocket(socketUrl: string, options: Options = {}):
|
|
|
// }
|
|
|
|
|
|
try {
|
|
|
- console.log(websocketRef.current, 'current');
|
|
|
+ // console.log(websocketRef.current, 'current');
|
|
|
websocketRef.current = new WebSocket(socketUrl);
|
|
|
|
|
|
websocketRef.current.onerror = (event) => {
|
|
|
+ isReconnect.current = true; // 开启重连
|
|
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
|
reconnect();
|
|
|
onError?.(event);
|
|
|
setReadyState(websocketRef.current?.readyState || ReadyState.Closed);
|
|
|
};
|
|
|
websocketRef.current.onopen = (event) => {
|
|
|
+ if (isReconnect.current && onReconnect) {
|
|
|
+ // 是否为重连
|
|
|
+ onReconnect();
|
|
|
+ }
|
|
|
onOpen?.(event);
|
|
|
reconnectTimesRef.current = 0;
|
|
|
setReadyState(websocketRef.current?.readyState || ReadyState.Closed);
|
|
|
@@ -79,10 +88,12 @@ export default function useWebSocket(socketUrl: string, options: Options = {}):
|
|
|
setLatestMessage(message);
|
|
|
};
|
|
|
websocketRef.current.onclose = (event) => {
|
|
|
+ isReconnect.current = true; // 开启重连
|
|
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
|
reconnect();
|
|
|
onClose?.(event);
|
|
|
setReadyState(websocketRef.current?.readyState || ReadyState.Closed);
|
|
|
+ Store.set(SystemConst.GLOBAL_WEBSOCKET, null);
|
|
|
};
|
|
|
Store.set(SystemConst.GLOBAL_WEBSOCKET, websocketRef.current);
|
|
|
} catch (error) {
|
|
|
@@ -91,22 +102,37 @@ export default function useWebSocket(socketUrl: string, options: Options = {}):
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+ const getTime = (time: number): number => {
|
|
|
+ const m = 60 * 1000;
|
|
|
+ if (time <= 5) {
|
|
|
+ return 3000;
|
|
|
+ } else if (time > 5 && time <= 10) {
|
|
|
+ return 10000;
|
|
|
+ } else if (time > 10 && time <= 20) {
|
|
|
+ return m;
|
|
|
+ }
|
|
|
+ return 5 * m;
|
|
|
+ };
|
|
|
+
|
|
|
/**
|
|
|
* 重连
|
|
|
*/
|
|
|
const reconnect = usePersistFn(() => {
|
|
|
- if (
|
|
|
- reconnectTimesRef.current < reconnectLimit &&
|
|
|
- websocketRef.current?.readyState !== ReadyState.Open
|
|
|
- ) {
|
|
|
- if (reconnectTimerRef.current) {
|
|
|
- clearTimeout(reconnectTimerRef.current);
|
|
|
- }
|
|
|
- reconnectTimerRef.current = setTimeout(() => {
|
|
|
- connectWs();
|
|
|
- reconnectTimesRef.current += 1;
|
|
|
- }, reconnectInterval);
|
|
|
+ if (lockReconnect.current) {
|
|
|
+ return;
|
|
|
}
|
|
|
+
|
|
|
+ if (reconnectTimerRef.current) {
|
|
|
+ clearTimeout(reconnectTimerRef.current);
|
|
|
+ }
|
|
|
+
|
|
|
+ lockReconnect.current = true;
|
|
|
+ const _time = getTime(reconnectTimesRef.current);
|
|
|
+ reconnectTimerRef.current = setTimeout(() => {
|
|
|
+ lockReconnect.current = false;
|
|
|
+ reconnectTimesRef.current += 1;
|
|
|
+ connectWs();
|
|
|
+ }, _time);
|
|
|
});
|
|
|
|
|
|
/**
|
|
|
@@ -142,7 +168,7 @@ export default function useWebSocket(socketUrl: string, options: Options = {}):
|
|
|
const disconnect = usePersistFn(() => {
|
|
|
if (reconnectTimerRef.current) clearTimeout(reconnectTimerRef.current);
|
|
|
|
|
|
- reconnectTimesRef.current = reconnectLimit;
|
|
|
+ reconnectTimesRef.current = 0;
|
|
|
websocketRef.current?.close();
|
|
|
});
|
|
|
|