/
kochkatech
/
CorpGame
Обзор
Документация
Войти
/
kochkatech
/
CorpGame
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
1
CI/CD
Аналитика
master
frontend/src/socket.ts
70 строк
4 KB
kochkareal
chore: добавлен .gitattributes, нормализованы переносы строк (LF везде, кроме .bat/.cmd)
06 авг 2026, 15:18
06 авг 2026, 15:18
c25ef1b
Код
Авторство
О чём код?
import { io, Socket } from 'socket.io-client'; import { useGameStore } from './store/useGameStore'; let socket: Socket | null = null; let currentKey: string | null = null; function wireConnectionState(s: Socket, onReconnect?: () => void) { const setConnected = useGameStore.getState().setConnected; // Снимаем предыдущие обработчики перед повторной привязкой — иначе при переиспользовании // сокета (тот же key) здесь остаётся СТАРЫЙ onReconnect от предыдущего вызова страницы, // и после разрыва связи (сон вкладки/Wi-Fi) актуальные данные никогда не подтягиваются — // выглядит так, будто экран «завис» и помогает только ручная перезагрузка страницы. s.off('connect'); s.off('disconnect'); s.off('connect_error'); s.on('connect', () => { setConnected(true); // На повторном коннекте (после обрыва Wi-Fi/сна вкладки) состояние могло устареть — // даём странице шанс перезапросить актуальные данные. onReconnect?.(); }); s.on('disconnect', () => setConnected(false)); s.on('connect_error', () => setConnected(false)); } /** * Одно соединение на вкладку. Роль (команда/админ/зритель) определяется сервером по кукам * или query-параметру. `key` идентифицирует текущее подключение (например, id сессии для * зрителя/админа) — повторный вызов с тем же key переиспользует сокет вместо пересоздания, * но обработчики connect/disconnect всегда перепривязываются к актуальному onReconnect. */ function connect(key: string, query?: Record<string, string>, onReconnect?: () => void): Socket { if (socket && currentKey === key) { wireConnectionState(socket, onReconnect); // Сокет мог быть уже подключён (или переподключиться незаметно) — не ждём следующего // события 'connect', даём странице шанс сразу освежить данные. if (socket.connected) onReconnect?.(); return socket; } socket?.disconnect(); currentKey = key; socket = io('/', { withCredentials: true, query, transports: ['websocket', 'polling'], }); wireConnectionState(socket, onReconnect); return socket; } /** Подключение для команды (роль определяется кукой team_token) */ export function connectSocket(viewerSessionId?: string, onReconnect?: () => void): Socket { if (viewerSessionId) return connect(`viewer:${viewerSessionId}`, { viewerSessionId }, onReconnect); return connect('team', undefined, onReconnect); } /** Подключение для админа, наблюдающего за конкретной сессией (кука admin_token + query sessionId) */ export function connectAdminSocket(sessionId: string, onReconnect?: () => void): Socket { return connect(`admin:${sessionId}`, { sessionId }, onReconnect); } export function getSocket(): Socket | null { return socket; } export function disconnectSocket() { socket?.disconnect(); socket = null; currentKey = null; }