WebSocket (клиент)

Полнодуплексный канал поверх TCP: сервер пушит сообщения клиенту в реальном времени.

Что это

HTTP-запрос с Upgrade: websocket превращает соединение в постоянный двунаправленный канал. В отличие от long-polling — экономно по трафику; в отличие от Server-Sent Events — двунаправленно и поддерживает бинарные данные.

Базовое использование

const ws = new WebSocket('wss://api.example.com/sync');

ws.addEventListener('open', () => {
  console.log('connected');
  ws.send(JSON.stringify({ type: 'subscribe', topic: 'rooms' }));
});

ws.addEventListener('message', (event) => {
  // event.data — string | Blob | ArrayBuffer
  const msg = JSON.parse(event.data);
  console.log(msg);
});

ws.addEventListener('close', (event) => {
  console.log('closed', event.code, event.reason);
  // переподключиться с экспоненциальным backoff
});

ws.addEventListener('error', (e) => console.error(e));

// Отправка
ws.send('text');
ws.send(JSON.stringify({ a: 1 }));
ws.send(new Uint8Array([1, 2, 3])); // бинарь

// Закрыть
ws.close(1000, 'bye');

Состояния

readyState Что
0 CONNECTING Открывается
1 OPEN Готов слать/принимать
2 CLOSING Закрывается
3 CLOSED Закрыт

Reconnect-обёртка (минимум)

function connect(url, onMessage) {
  let ws;
  let attempt = 0;

  const open = () => {
    ws = new WebSocket(url);
    ws.onopen = () => { attempt = 0; };
    ws.onmessage = (e) => onMessage(JSON.parse(e.data));
    ws.onclose = () => {
      const delay = Math.min(1000 * 2 ** attempt++, 30_000);
      setTimeout(open, delay);
    };
  };
  open;
  return  => ws.close();
}

Поддержка

Везде. ws:// (plaintext) и wss:// (TLS — на проде ОБЯЗАТЕЛЬНО).

Подводные камни

  • На фоне в браузере может уснуть (Chrome не закрывает, но throttles)
  • Нет встроенного reconnect — пиши сам
  • Нет встроенного ping/pong доступного из JS — heartbeat руками (отправляй пустое сообщение раз в N секунд)
  • Через прокси/корпоративные firewall'ы wss:// иногда блокируется
  • Не путать с Socket.IO (это библиотека поверх WS с fallback'ами)
  • Заголовки кастомные в WebSocket ctor нельзя установить (только subprotocol через 2-й аргумент)

Альтернативы

Когда
WebSocket Bi-directional real-time
SSE (EventSource) Только сервер→клиент, через HTTP
WebTransport HTTP/3, новее, не везде
WebRTC DataChannel P2P между браузерами

Используется в bootcamp

  • Любая real-time задача — чаты, live-обновления, синхронизация
  • В local-first архитектуре (Метархия) — единственный канал между Service Worker и сервером

Ссылки

🎓 Источники

См. также