Короткий ответ: подключение к множеству WebSocket-серверов нужно организовывать через единый менеджер соединений. Не создавайте new WebSocket(...) в случайных компонентах и функциях. Храните сокеты в Map, задавайте имя каждому серверу, проверяйте readyState, закрывайте соединения централизованно и отдельно продумайте переподключение
Схема:
ConnectionManager
prices -> wss://prices.example.com/ws
chat -> wss://chat.example.com/ws
events -> wss://events.example.com/ws
Минимальный менеджер соединений
class WebSocketManager {
constructor() {
this.connections = new Map();
}
connect(name, url) {
if (this.connections.has(name)) {
return this.connections.get(name);
}
const socket = new WebSocket(url);
socket.addEventListener("open", () => {
console.log(`${name}: connected`);
});
socket.addEventListener("close", () => {
console.log(`${name}: closed`);
this.connections.delete(name);
});
socket.addEventListener("error", () => {
console.log(`${name}: error`);
});
this.connections.set(name, socket);
return socket;
}
send(name, data) {
const socket = this.connections.get(name);
if (!socket || socket.readyState !== WebSocket.OPEN) {
return false;
}
socket.send(JSON.stringify(data));
return true;
}
close(name) {
const socket = this.connections.get(name);
socket?.close(1000, "Manual close");
this.connections.delete(name);
}
closeAll() {
for (const [name, socket] of this.connections) {
socket.close(1000, `Close ${name}`);
}
this.connections.clear();
}
}
Использование:
const manager = new WebSocketManager();
manager.connect("prices", "wss://example.com/prices");
manager.connect("chat", "wss://example.com/chat");
manager.send("chat", {
type: "message",
text: "Привет",
});
Не все соединения нужно открывать сразу
Если пользователь не открыл чат, не нужно держать чат-сокет. Если график не виден на странице, не нужно подписываться на поток цен. Правильная организация часто означает не “открыть все серверы”, а “открывать нужное соединение в нужный момент”
Пример:
- глобальные уведомления — после авторизации;
- чат — при входе в раздел чата;
- live-график — при открытии графика;
- админские события — только для пользователя с правами.
Переподключение
Для каждого сервера задайте свою стратегию. Не делайте бесконечный агрессивный reconnect каждую миллисекунду
function reconnectWithDelay(connect, attempt) {
const delay = Math.min(1000 * 2 ** attempt, 30000);
setTimeout(connect, delay);
}
В реальном коде добавьте лимит попыток, jitter и проверку: нужно ли соединение еще пользователю
Еще один важный момент — не переподключайте сокет, который пользователь закрыл осознанно. Для этого храните флаг:
const connectionState = {
chat: { shouldReconnect: true },
};
При logout или закрытии раздела ставьте shouldReconnect = false, а уже потом вызывайте close(). Иначе приложение само восстановит соединение, которое вы только что пытались закрыть
Авторизация
Если серверы требуют токен, не передавайте секреты в адрес без необходимости. Часто используют короткоживущий токен, cookie-сессию или первое сообщение после подключения:
socket.addEventListener("open", () => {
socket.send(JSON.stringify({
type: "auth",
token: accessToken,
}));
});
Выбор зависит от архитектуры. Главное — не открывать публичный WebSocket, через который можно получить личные данные
Частые ошибки
Первая ошибка — десятки соединений без учета лимитов браузера и сервера. Даже если WebSocket постоянный, он не бесплатный
Вторая ошибка — потерять ссылки на сокеты. Потом их невозможно корректно закрыть
Третья ошибка — отправлять данные до open. Используйте очередь сообщений или проверку readyState
Четвертая ошибка — один общий reconnect для всех серверов. Разные каналы могут иметь разные правила: чат можно переподключать мягче, критичные уведомления — активнее
Самопроверка
Создайте три подключения через менеджер, отправьте сообщение только в одно из них, затем вызовите closeAll(). В DevTools Network все открытые WS-соединения должны закрыться. Если какое-то соединение осталось, значит оно было создано в обход менеджера
Что почитать дальше по WebSocket
Если нужен общий маршрут по теме, откройте рубрику WebSocket. Для соседних задач пригодятся эти разборы:
- OBS WebSocket скачать: как установить плагин и проверить подключение
- OBS WebSocket: подключение к стриму и автоматизация сцен
- Как организовать работу с WebSocket
- Как правильно маскировать и демаскировать фреймы WebSocket