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:
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')
+ })
+
})
}