Короткий ответ: в JavaScript нельзя магически закрыть “абсолютно все” WebSocket-соединения, если вы не сохранили ссылки на них. Правильный способ — создавать WebSocket через общий wrapper, складывать каждый socket в Set, а при logout, уходе со страницы или остановке приложения вызывать close() для всех открытых соединений
Главное правило: если ссылка на WebSocket потеряна, управлять этим соединением из вашего кода уже нельзя
Реестр всех WebSocket-соединений
Создайте модуль websocketRegistry.js:
const sockets = new Set();
export function createManagedWebSocket(url, protocols) {
const socket = new WebSocket(url, protocols);
sockets.add(socket);
socket.addEventListener("close", () => {
sockets.delete(socket);
});
return socket;
}
export function closeAllWebSockets(code = 1000, reason = "Application shutdown") {
for (const socket of sockets) {
if (
socket.readyState === WebSocket.OPEN ||
socket.readyState === WebSocket.CONNECTING
) {
socket.close(code, reason);
}
}
sockets.clear();
}
Теперь вместо new WebSocket(...) используйте:
import { createManagedWebSocket, closeAllWebSockets } from "./websocketRegistry.js";
const chatSocket = createManagedWebSocket("wss://example.com/chat");
const notifySocket = createManagedWebSocket("wss://example.com/notifications");
document.querySelector("#logout").addEventListener("click", () => {
closeAllWebSockets(1000, "Logout");
});
Так вы контролируете все соединения, созданные через ваш код
Закрытие при уходе со страницы
Для браузера полезно закрывать соединения на pagehide:
window.addEventListener("pagehide", () => {
closeAllWebSockets(1000, "Page hidden");
});
pagehide лучше подходит для ухода со страницы, чем грубая ставка только на beforeunload. Он также связан с поведением bfcache: открытые WebSocket-соединения могут мешать браузеру эффективно сохранять страницу в кэше навигации
В React
В React обычно закрывают WebSocket в cleanup-функции эффекта:
useEffect(() => {
const socket = createManagedWebSocket("wss://example.com/chat");
socket.addEventListener("message", (event) => {
console.log(event.data);
});
return () => {
socket.close(1000, "Component unmounted");
};
}, []);
А если нужно закрыть все соединения при выходе пользователя:
function logout() {
closeAllWebSockets(1000, "Logout");
clearUserSession();
}
На сервере Node.js
Если вопрос про серверную сторону, там логика другая. В ws можно пройти по клиентам сервера:
function closeAllClients(wss) {
for (const client of wss.clients) {
if (client.readyState === client.OPEN) {
client.close(1000, "Server shutdown");
}
}
}
Перед остановкой процесса можно закрыть клиентов и сам сервер:
closeAllClients(wss);
wss.close();
Это не закрывает WebSocket во всем интернете. Это закрывает соединения, которые держит конкретный серверный процесс
Почему sockets.clear() недостаточно
sockets.clear() удаляет ссылки из Set, но не закрывает реальные соединения. Сначала вызывайте socket.close(), потом чистите коллекцию. Иначе вы просто потеряете управление над открытыми сокетами
Правильная последовательность:
for (const socket of sockets) {
socket.close(1000, "Cleanup");
}
sockets.clear();
Частые ошибки
Первая ошибка — создавать WebSocket в разных местах через new WebSocket(...), а потом пытаться закрыть все одним вызовом. Если нет общего реестра, закрыть все не получится
Вторая ошибка — закрывать только OPEN, забывая про CONNECTING. Если пользователь быстро ушел со страницы, сокет может еще подключаться. Его тоже можно закрыть
Третья ошибка — не удалять закрытые сокеты из Set. Тогда реестр будет расти и хранить старые ссылки
Четвертая ошибка — думать, что close() мгновенно завершает все сетевые процессы. Закрытие проходит через close handshake, поэтому событие close может прийти чуть позже
Самопроверка
Создайте два соединения через createManagedWebSocket, дождитесь open, затем вызовите closeAllWebSockets(). В DevTools Network во вкладке WS оба соединения должны перейти в закрытое состояние
Потом попробуйте создать один сокет напрямую через new WebSocket(...). Ваш closeAllWebSockets() его не закроет. Это демонстрирует главное ограничение: закрывать можно только то, чем вы управляете
Что почитать дальше по WebSocket
Если нужен общий маршрут по теме, откройте рубрику WebSocket. Для соседних задач пригодятся эти разборы:
- WebSocket на JavaScript и Node.js: мини-чат в браузере
- Django: как подружить Celery с WebSocket
- Django: как сохранить биржевые данные, полученные по WebSocket
- FastAPI WebSocket: уведомления в браузер



