0Pricing
Frontend Academy · Урок

API WebSocket: открытие, сообщение, закрытие и ошибка

Создайте соединение WebSocket, отправляйте и принимайте сообщения в обработчике события message и обрабатывайте ошибки соединения и корректное закрытие

«API WebSocket: открытие, сообщение, закрытие и ошибка» — бесплатный урок Frontend Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Frontend Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Frontend Academy содержит 4 уроков всего.

Зачем нужны WebSockets?

HTTP работает по схеме «запрос–ответ». Для приложений, работающих в реальном времени (чатов, многопользовательских игр, оперативных обновлений), нужна постоянная двусторонняя связь. WebSockets создают одно TCP-соединение, которое остаётся открытым и позволяет обеим сторонам отправлять сообщения в любой момент.

Создание WebSocket

Создайте WebSocket с URL-адресом ws:// или wss://. Браузер самостоятельно выполняет рукопожатие для обновления соединения.

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

// Always use wss:// (secure) in production

Четыре события

WebSocket поддерживает четыре типа событий: open (соединение установлено), message (данные получены), close (соединение завершено), error (произошла проблема).

ws.addEventListener('open', () => {
  console.log('Connected');
  ws.send(JSON.stringify({ type: 'subscribe', channel: 'updates' }));
});

ws.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  console.log('Received:', data);
});

ws.addEventListener('close', (event) => {
  console.log('Closed:', event.code, event.reason);
});

ws.addEventListener('error', (event) => {
  console.error('Error:', event);
});

Отправка сообщений

Используйте ws.send(). Метод принимает строки, ArrayBuffers, двоичные объекты или ArrayBufferView. Для структурированных данных сначала вызовите JSON.stringify.

ws.send('hello');
ws.send(JSON.stringify({ type: 'chat', text: 'Hi' }));

// Binary:
const buffer = new ArrayBuffer(8);
ws.send(buffer);

Получение сообщений

Проверьте event.data — его тип соответствует тому, что отправил сервер. Для объектов используйте JSON.parse.

ws.addEventListener('message', (event) => {
  // typeof event.data: string | ArrayBuffer | Blob
  if (typeof event.data === 'string') {
    const msg = JSON.parse(event.data);
    handleMessage(msg);
  }
});

Состояние соединения (readyState)

Проверьте ws.readyState: CONNECTING=0, OPEN=1, CLOSING=2, CLOSED=3. Не отправляйте данные до перехода в состояние OPEN.

if (ws.readyState === WebSocket.OPEN) {
  ws.send(message);
} else {
  console.warn('Not connected yet');
}

Корректное закрытие

Вызовите ws.close(code, reason). Стандартные коды закрытия: 1000 (нормальное закрытие), 1001 (уход со страницы), 1008 (нарушение политики), 1011 (ошибка сервера).

ws.close(1000, 'User logged out');

Стратегия переподключения

WebSockets отключаются при изменении сети, перезапуске сервера и в других подобных ситуациях. Реализуйте переподключение с экспоненциальной задержкой.

let reconnectDelay = 1000;

function connect() {
  const ws = new WebSocket('wss://api/realtime');
  ws.addEventListener('open', () => { reconnectDelay = 1000; });
  ws.addEventListener('close', () => {
    setTimeout(connect, reconnectDelay);
    reconnectDelay = Math.min(reconnectDelay * 2, 30000);
  });
  return ws;
}

Контрольные сигналы и поддержание соединения

Простои WebSockets могут привести к отключению прокси-сервером или балансировщиком нагрузки примерно через 60 секунд. Отправляйте контрольный сигнал каждые 25–30 секунд, чтобы соединение оставалось активным.

let pingInterval;
ws.addEventListener('open', () => {
  pingInterval = setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: 'ping' }));
    }
  }, 25000);
});
ws.addEventListener('close', () => clearInterval(pingInterval));

Аутентификация

WebSockets не поддерживают пользовательские заголовки. Варианты: 1) передать токен аутентификации в строке запроса (?token=jwt) URL-адреса WS; 2) отправить сообщение аутентификации после события open; 3) использовать cookie (для одного источника это работает автоматически).

// Query string:
const ws = new WebSocket(`wss://api/realtime?token=${jwt}`);

// Auth message:
ws.addEventListener('open', () => {
  ws.send(JSON.stringify({ type: 'auth', token: jwt }));
});

Хук React для WebSockets

Инкапсулируйте жизненный цикл WS в пользовательском хуке, чтобы избежать утечки соединений.

function useWebSocket(url) {
  const [messages, setMessages] = useState([]);
  const wsRef = useRef(null);

  useEffect(() => {
    const ws = new WebSocket(url);
    wsRef.current = ws;
    ws.addEventListener('message', (e) => {
      setMessages(m => [...m, JSON.parse(e.data)]);
    });
    return () => ws.close();
  }, [url]);

  return { messages, send: (msg) => wsRef.current?.send(JSON.stringify(msg)) };
}

WebSocket, HTTP/2 и SSE

WebSocket: полнодуплексная связь, данные могут отправлять обе стороны. Серверная отправка в HTTP/2: устарела. Server-Sent Events: только от сервера к клиенту, проще и с автоматическим переподключением. Выбирайте WS, когда клиенту тоже нужно отправлять данные (например, в чате), а SSE — для односторонних уведомлений.

Быстрая проверка

Какой стандартный код закрытия WebSocket используется для нормального преднамеренного закрытия (например, когда пользователь вышел из системы)?

Повторение: API WebSocket

new WebSocket('wss://...') открывает соединение. Четыре события: open, message, close, error. send() принимает строку, ArrayBuffer или Blob; для объектов используйте JSON.stringify. Проверяйте readyState перед отправкой. Для корректного закрытия используйте close(1000). Выполняйте переподключение с экспоненциальной задержкой. Отправляйте контрольный сигнал каждые 25 секунд, чтобы соединение оставалось активным. Аутентификация выполняется через строку запроса или сообщение аутентификации. В React оберните всё в хук.

Часто задаваемые вопросы

Урок «API WebSocket: открытие, сообщение, закрытие и ошибка» бесплатный?

Да — полный текст урока «API WebSocket: открытие, сообщение, закрытие и ошибка» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Frontend Academy, подпишись на CoddyKit PRO. Курс Frontend Academy содержит 4 уроков всего.

Чему я научусь в уроке «API WebSocket: открытие, сообщение, закрытие и ошибка»?

Создайте соединение WebSocket, отправляйте и принимайте сообщения в обработчике события message и обрабатывайте ошибки соединения и корректное закрытие Ты практикуешь Frontend Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Frontend Academy?

Предыдущий опыт не требуется. Frontend Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «API WebSocket: открытие, сообщение, закрытие и ошибка»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Frontend Academy?

Да. Каждый урок Frontend Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. API WebSocket: открытие, сообщение, закрытие и ошибка
  2. Интеграция клиента Socket.io
  3. Server-Sent Events для однонаправленной потоковой передачи
  4. Шаблоны интерфейсов реального времени
← Назад к Frontend Academy