WebSocket на TypeScript: Создание Real-Time приложений

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

WebSocket на TypeScript: создание real-time приложений

Современные веб-приложения требуют мгновенного обмена данными между клиентом и сервером. Протокол WebSocket предоставляет постоянное двустороннее соединение, что делает его идеальным для создания чатов, систем уведомлений, онлайн-игр и других real-time сервисов. В этой статье мы подробно разберем, как работать с WebSocket на TypeScript — от настройки сервера до реализации клиента.

Что такое WebSocket и зачем он нужен?

WebSocket — это протокол связи, который обеспечивает полнодуплексный канал поверх одного TCP-соединения. В отличие от традиционного HTTP, где клиент отправляет запрос и ждет ответ, WebSocket позволяет серверу самостоятельно инициировать отправку данных клиенту.

Основные преимущества WebSocket:

  • Постоянное соединение — не нужно устанавливать новое соединение для каждого запроса
  • Низкая задержка — данные передаются мгновенно без оверхэда HTTP-заголовков
  • Двусторонняя связь — сервер может отправлять данные без запроса от клиента
  • Эффективность — меньше трафика по сравнению с polling-решениями

WebSocket широко применяется в финансовых приложениях (биржевые котировки), социальных сетях (лайки, комментарии в реальном времени), многопользовательских играх, системах мониторинга и IoT.

Настройка WebSocket сервера на TypeScript

Для создания сервера мы будем использовать популярную библиотеку ws. Установите ее через npm:

npm init -y
npm install ws
npm install -D typescript @types/ws @types/node
npx tsc --init

Создадим файл server.ts:

import { WebSocketServer, WebSocket } from 'ws';

const PORT = 8080;
const wss = new WebSocketServer({ port: PORT });

interface CustomMessage {
  type: string;
  payload: any;
}

wss.on('connection', (ws: WebSocket) => {
  console.log('Новый клиент подключился');

  // Отправляем приветственное сообщение
  const welcomeMessage: CustomMessage = {
    type: 'welcome',
    payload: { message: 'Добро пожаловать на сервер!' }
  };
  ws.send(JSON.stringify(welcomeMessage));

  // Обработка входящих сообщений
  ws.on('message', (data: Buffer) => {
    try {
      const message: CustomMessage = JSON.parse(data.toString());
      
      switch (message.type) {
        case 'chat':
          // Рассылаем сообщение всем подключенным клиентам
          broadcast(message, ws);
          break;
        case 'ping':
          ws.send(JSON.stringify({ type: 'pong', payload: {} }));
          break;
        default:
          console.log('Неизвестный тип сообщения:', message.type);
      }
    } catch (error) {
      console.error('Ошибка обработки сообщения:', error);
    }
  });

  ws.on('close', () => {
    console.log('Клиент отключился');
  });

  ws.on('error', (error: Error) => {
    console.error('Ошибка WebSocket:', error);
  });
});

function broadcast(message: CustomMessage, sender: WebSocket) {
  wss.clients.forEach((client) => {
    if (client !== sender && client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify(message));
    }
  });
}

console.log(`WebSocket сервер запущен на ws://localhost:${PORT}`);

Запустите сервер командой npx ts-node server.ts. Сервер будет слушать порт 8080 и обрабатывать входящие соединения.

Создание WebSocket клиента на TypeScript

Клиентскую часть можно реализовать как для браузера, так и для Node.js. Рассмотрим оба варианта.

Браузерный клиент

Создадим файл client.ts для использования в веб-приложении:

class WebSocketClient {
  private socket: WebSocket;
  private url: string;

  constructor(url: string) {
    this.url = url;
    this.socket = new WebSocket(url);
    this.init();
  }

  private init(): void {
    this.socket.onopen = () => {
      console.log('Соединение установлено');
      this.sendMessage('ping', {});
    };

    this.socket.onmessage = (event: MessageEvent) => {
      const message = JSON.parse(event.data);
      
      switch (message.type) {
        case 'welcome':
          console.log('Сервер:', message.payload.message);
          break;
        case 'chat':
          this.displayMessage(message.payload);
          break;
        case 'pong':
          console.log('Сервер ответил на ping');
          break;
        default:
          console.log('Получено сообщение:', message);
      }
    };

    this.socket.onclose = () => {
      console.log('Соединение закрыто');
    };

    this.socket.onerror = (error: Event) => {
      console.error('Ошибка WebSocket:', error);
    };
  }

  public sendMessage(type: string, payload: any): void {
    if (this.socket.readyState === WebSocket.OPEN) {
      const message = JSON.stringify({ type, payload });
      this.socket.send(message);
    } else {
      console.error('Соединение не открыто');
    }
  }

  private displayMessage(payload: any): void {
    // Здесь может быть логика отображения в UI
    console.log('Сообщение:', payload);
  }

  public close(): void {
    this.socket.close();
  }
}

// Использование
const client = new WebSocketClient('ws://localhost:8080');
client.sendMessage('chat', { text: 'Привет всем!' });

Node.js клиент

Для серверного клиента используем библиотеку ws:

import WebSocket from 'ws';

const ws = new WebSocket('ws://localhost:8080');

ws.on('open', () => {
  console.log('Подключено к серверу');
  
  // Отправляем тестовое сообщение
  ws.send(JSON.stringify({
    type: 'chat',
    payload: { text: 'Привет от Node.js клиента!' }
  }));
});

ws.on('message', (data: WebSocket.Data) => {
  const message = JSON.parse(data.toString());
  console.log('Получено:', message);
});

ws.on('close', () => {
  console.log('Соединение закрыто');
});

Практический пример: real-time чат

Соберем полноценное приложение чата с использованием TypeScript. Создадим структуру проекта:

chat-app/
├── server/
│   ├── server.ts
│   └── types.ts
├── client/
│   ├── index.html
│   └── client.ts
└── package.json

Файл types.ts для общих типов:

export interface ChatMessage {
  username: string;
  text: string;
  timestamp: number;
}

export interface WSMessage {
  type: 'chat' | 'join' | 'leave' | 'users';
  payload: ChatMessage | string[] | { username: string };
}

Обновленный сер

Блоги

Рекомендаций по книгам