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

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

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

Начать курс

WebSocket на TypeScript: Создаем real-time приложения

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

Что такое WebSocket и почему TypeScript?

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

TypeScript добавляет к JavaScript статическую типизацию, что критически важно для проектов с WebSocket. Типы помогают избежать ошибок при обработке сообщений и делают код более предсказуемым. Например, вы можете определить интерфейс для входящих и исходящих сообщений:


interface ChatMessage {
    type: 'message' | 'join' | 'leave';
    user: string;
    text?: string;
    timestamp: number;
}

interface ServerResponse {
    status: 'ok' | 'error';
    data?: ChatMessage;
    error?: string;
}

Такой подход значительно упрощает отладку и поддержку кода.

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

Для создания сервера мы будем использовать библиотеку ws — популярную реализацию WebSocket для Node.js. Установим зависимости:


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

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


import { WebSocketServer, WebSocket } from 'ws';

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

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

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

    // Обрабатываем входящие сообщения
    ws.on('message', (data: Buffer) => {
        try {
            const message = JSON.parse(data.toString());
            console.log('Получено:', message);

            // Рассылаем сообщение всем подключенным клиентам
            wss.clients.forEach((client) => {
                if (client.readyState === WebSocket.OPEN) {
                    client.send(JSON.stringify({
                        type: 'broadcast',
                        user: message.user,
                        text: message.text,
                        timestamp: Date.now()
                    }));
                }
            });
        } catch (error) {
            ws.send(JSON.stringify({
                type: 'error',
                message: 'Некорректный формат сообщения'
            }));
        }
    });

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

console.log('WebSocket сервер запущен на ws://localhost:8080');

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

WebSocket клиент на TypeScript

Теперь создадим клиентскую часть. TypeScript отлично работает в браузере, поэтому мы напишем клиент на чистом TypeScript, который будет компилироваться в JavaScript.

Файл client.ts:


interface ChatMessage {
    type: string;
    user?: string;
    text?: string;
    message?: string;
    timestamp?: number;
}

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('Система', 'Пользователь вошел в чат');
        };

        this.socket.onmessage = (event: MessageEvent) => {
            const data: ChatMessage = JSON.parse(event.data);
            this.handleMessage(data);
        };

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

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

    private handleMessage(data: ChatMessage): void {
        switch (data.type) {
            case 'system':
                console.log(`[Система] ${data.message}`);
                break;
            case 'broadcast':
                console.log(`[${data.user}] ${data.text} (${new Date(data.timestamp!).toLocaleTimeString()})`);
                break;
            case 'error':
                console.error(`[Ошибка] ${data.message}`);
                break;
            default:
                console.log('Неизвестный тип сообщения:', data);
        }
    }

    public sendMessage(user: string, text: string): void {
        const message: ChatMessage = {
            type: 'message',
            user: user,
            text: text
        };
        this.socket.send(JSON.stringify(message));
    }

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

// Использование:
const client = new WebSocketClient('ws://localhost:8080');

Клиент автоматически подключается к серверу, обрабатывает различные типы сообщений и предоставляет удобный интерфейс для отправки данных.

Расширенные возможности: аутентификация и комнаты

Для создания полноценного real-time приложения часто требуется аутентификация и разделение на комнаты. Рассмотрим, как добавить эти функции.

Аутентификация через токен:


// Сервер
import { IncomingMessage } from 'http';

wss.on('connection', (ws: WebSocket, req: IncomingMessage) => {
    const token = new URL(req.url!, `http://${req.headers.host}`).searchParams.get('token');
    
    if (!token || !validateToken(token)) {
        ws.close(4001, 'Недействительный токен');
        return;
    }

    // Продолжаем обработку
});

// Клиент
const client = new WebSocketClient('ws://localhost:8080?token=ваш_токен');

Разделение на комнаты:


interface Room {
    name: string;
    clients: Set<WebSocket>;
}

const rooms: Map<string, Room> = new Map();

function joinRoom(ws: WebSocket, roomName: string): void {
    if (!rooms.has(roomName)) {
        rooms.set(roomName, { name: roomName, clients: new Set() });
    }
    rooms.get(roomName)!.clients.add(ws);
}

function broadcastToRoom(roomName: string, message: string, sender: WebSocket): void {
    const room = rooms.get(roomName);
    if (room) {
        room.clients.forEach(client => {
            if (client !== sender && client.readyState === WebSocket.OPEN) {
                client.send(message);
            }
        });
    }
}

Эти улучшения позволяют создавать масштаби

Блоги

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