dh_demo

DreamHanks demo project
git clone git://git.lair.cx/dh_demo
Log | Files | Refs | README

commit ca207f05a0ee91626efed9cda99687646dd33293
parent 0ed92ba978d9bda44941b7c0ca2a53e1c2757920
Author: Yongbin Kim <iam@yongbin.kim>
Date:   Sun, 29 Jan 2023 03:48:19 +0900

fix: 페이지가 변경될 때 마다 매번 소켓에 다시 접속하던 문제 수정

Signed-off-by: Yongbin Kim <iam@yongbin.kim>

Diffstat:
Mcomponents/contexts/SocketContext.tsx | 40+++++++++++++++++++++++++---------------
Mlib/sockets.ts | 50++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 67 insertions(+), 23 deletions(-)

diff --git a/components/contexts/SocketContext.tsx b/components/contexts/SocketContext.tsx @@ -7,26 +7,36 @@ const SocketContext = createContext<SocketClient>(null as any) export function SocketProvider ({ children }: { children: ReactNode }) { const router = useRouter() const client = useMemo(() => new SocketClient(), []) - const [reconnectDependency, reconnect] = useReducer(v => !v, false) - const reconnectTimeoutRef = useRef<any>(null) useEffect(() => { - client.connect() - .then(() => { - client.changePath(router.pathname) - }, () => { - if (reconnectTimeoutRef.current) { - clearTimeout(reconnectTimeoutRef.current) - } - reconnectTimeoutRef.current = setTimeout(() => reconnect(), 5000) - }) + let connTimeout: any + + if (client.isConnected) { + return + } + + const tryConnect = () => { + client.connect() + .then(() => { + + }, () => { + connTimeout = setTimeout(tryConnect, 1000) + }) + } + + tryConnect() + return () => { - client.disconnect() - if (reconnectTimeoutRef.current) { - clearTimeout(reconnectTimeoutRef.current) + if (connTimeout != null) { + clearTimeout(connTimeout) } } - }, [client, router.pathname, reconnectDependency]) + }, []) + + useEffect(() => { + client.wait() + .then(() => client.changePath(router.pathname)) + }, [router.pathname]) return ( <SocketContext.Provider value={client}> diff --git a/lib/sockets.ts b/lib/sockets.ts @@ -1,4 +1,5 @@ import { createNanoEvents, Emitter } from 'nanoevents' +import { remove } from 'next/dist/build/webpack/loaders/resolve-url-loader/lib/file-protocol' interface SocketEvent { payload: string @@ -23,25 +24,58 @@ export class SocketClient { return this.socket?.readyState === WebSocket.OPEN } + wait () { + return new Promise<void>((resolve) => { + const check = () => { + if (this.isConnected) { + setTimeout(() => resolve(), 500) + return + } + + setTimeout(check, 100) + } + + check() + }) + } + connect () { - return new Promise((resolve, reject) => { + return new Promise<void>((resolve, reject) => { + const self = this + this.socket = new WebSocket(process.env.WIKI_SOCKET_URL ?? 'ws://localhost:3001/ws') - this.socket.addEventListener('close', () => { - console.log('SocketClient: disconnected') + function handleClose () { + removePromiseListeners() reject() - }) + } + + function handleOpen () { + removePromiseListeners() + setTimeout(() => { + resolve() + }, 500) + } + + function removePromiseListeners () { + self.socket?.removeEventListener('open', handleOpen) + self.socket?.removeEventListener('close', handleClose) + } - this.socket.addEventListener('message', event => { + this.socket.addEventListener('open', handleOpen) + this.socket.addEventListener('close', handleClose) + + this.socket.addEventListener('message', (event) => { this.handleMessage(event.data) }) this.socket.addEventListener('open', () => { console.log('SocketClient: connected') - setTimeout(() => { - resolve(this) - }, 500) }) + this.socket.addEventListener('close', () => { + console.log('SocketClient: disconnected') + }) + }) }