Работа с WebSocket

WebSocket представляет собой протокол двусторонней связи между клиентом и сервером, позволяющий отправлять и получать данные в режиме реального времени без постоянного опроса сервера. В Angular интеграция WebSocket осуществляется через сервисы и RxJS, что обеспечивает удобное управление потоками данных и подписками.


Основные принципы WebSocket

WebSocket соединение открывается через объект WebSocket или специализированные библиотеки, такие как rxjs/webSocket. Основные методы объекта WebSocket:

  • new WebSocket(url: string) — создание соединения.
  • send(data: any) — отправка данных на сервер.
  • close() — закрытие соединения.
  • События onopen, onmessage, onerror, onclose — обработка жизненного цикла соединения.

Особенность WebSocket в Angular заключается в интеграции с RxJS потоками, что позволяет легко управлять подписками и автоматическим закрытием соединения при уничтожении компонентов.


Создание сервиса для WebSocket

В Angular рекомендуется обернуть WebSocket в сервис для централизованного управления соединением и повторного использования.

import { Injectable, OnDestroy } from '@angular/core';
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
import { Observable, Subject } from 'rxjs';
import { retryWhen, delay, takeUntil } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class WebSocketService implements OnDestroy {
  private socket$: WebSocketSubject<any>;
  private destroy$ = new Subject<void>();

  constructor() {
    this.connect();
  }

  private connect(): void {
    this.socket$ = webSocket('ws://localhost:8080');

    this.socket$
      .pipe(
        retryWhen(errors => errors.pipe(delay(2000))),
        takeUntil(this.destroy$)
      )
      .subscribe(
        message => this.onMessage(message),
        err => console.error('WebSocket error:', err),
        () => console.warn('WebSocket connection closed')
      );
  }

  sendMessage(msg: any): void {
    if (this.socket$) {
      this.socket$.next(msg);
    }
  }

  onMessage(msg: any): void {
    console.log('Received message:', msg);
  }

  close(): void {
    this.destroy$.next();
    this.socket$.complete();
  }

  ngOnDestroy(): void {
    this.close();
  }
}

Ключевые моменты сервиса:

  • Использование WebSocketSubject из rxjs/webSocket для интеграции с RxJS.
  • Автоматическое переподключение через retryWhen.
  • Управление жизненным циклом через takeUntil и Subject, что предотвращает утечки памяти.
  • Универсальные методы sendMessage и onMessage для отправки и получения данных.

Подключение WebSocket к компоненту

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

import { Component, OnInit, OnDestroy } from '@angular/core';
import { WebSocketService } from './web-socket.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-chat',
  template: `
    <div>
      <input [(ngModel)]="message" placeholder="Введите сообщение">
      <button (click)="send()">Отправить</button>
    </div>
    <ul>
      <li *ngFor="let msg of messages">{{ msg }}</li>
    </ul>
  `
})
export class ChatComponent implements OnInit, OnDestroy {
  message: string = '';
  messages: string[] = [];
  private subscription: Subscription;

  constructor(private wsService: WebSocketService) {}

  ngOnInit(): void {
    this.subscription = this.wsService.socket$
      .subscribe(msg => this.messages.push(msg));
  }

  send(): void {
    if (this.message.trim()) {
      this.wsService.sendMessage(this.message);
      this.message = '';
    }
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

Особенности взаимодействия компонента с WebSocket:

  • Подписка на поток данных через WebSocketSubject.
  • Очистка подписки при уничтожении компонента, чтобы избежать утечек.
  • Использование двухстороннего связывания ngModel для ввода сообщений.

Управление событиями WebSocket

WebSocket в Angular позволяет обрабатывать события соединения:

  • onopen — соединение установлено.
  • onmessage — получено новое сообщение.
  • onerror — ошибка соединения.
  • onclose — соединение закрыто.

Для более сложных сценариев, таких как переподключение, фильтрация сообщений по типу или групповая рассылка, рекомендуется использовать RxJS операторы filter, map, share и retryWhen. Это позволяет строить масштабируемые архитектуры для real-time приложений.


Применение WebSocket в приложениях

Примеры использования:

  • Чаты и системы обмена сообщениями.
  • Реализация уведомлений в реальном времени.
  • Мониторинг состояния серверов или IoT-устройств.
  • Онлайн-игры с синхронизацией игроков.

Преимущества использования в Angular:

  • Интеграция с RxJS позволяет легко комбинировать потоки WebSocket с другими потоками данных.
  • Централизованное управление через сервис упрощает поддержку и тестирование.
  • Реактивный подход упрощает масштабирование приложения.

Использование WebSocket в Angular обеспечивает гибкое, эффективное и устойчивое решение для приложений с реальным временем, позволяя строить сложные интерфейсы с высокой отзывчивостью.