Реактивное программирование в TypeScript: библиотека RxJS

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

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

Начать курс

Реактивное программирование в TypeScript с помощью RxJS

Реактивное программирование — это парадигма разработки, ориентированная на асинхронные потоки данных и распространение изменений. В экосистеме TypeScript ключевым инструментом для реализации этой парадигмы является библиотека RxJS (Reactive Extensions for JavaScript). Она предоставляет мощный набор инструментов для работы с событиями, асинхронными запросами и любыми потоками данных, делая код более предсказуемым и легко поддерживаемым.

RxJS основана на паттерне Observer и концепции Observable (наблюдаемого потока). Observable представляет собой источник данных, который может генерировать значения с течением времени. На него можно подписаться с помощью Observer, который реагирует на три типа событий: next (новое значение), error (ошибка) и complete (завершение потока).

Установка и настройка RxJS в TypeScript

Для начала работы установите RxJS через npm:

npm install rxjs

RxJS полностью совместим с TypeScript и имеет встроенную типизацию. Вот простейший пример создания Observable:

import { Observable } from 'rxjs';

const observable = new Observable<number>(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
  subscriber.next(3);
  setTimeout(() => {
    subscriber.next(4);
    subscriber.complete();
  }, 1000);
});

observable.subscribe({
  next: (value) => console.log('Получено:', value),
  error: (err) => console.error('Ошибка:', err),
  complete: () => console.log('Поток завершён')
});

Основные концепции RxJS

Чтобы эффективно использовать реактивное программирование, важно понимать ключевые строительные блоки RxJS:

  • Observable — источник данных, который может быть синхронным или асинхронным.
  • Observer — объект с методами next, error, complete, который реагирует на события Observable.
  • Subscription — объект, представляющий выполнение Observable. Его можно отменить с помощью метода unsubscribe().
  • Operators — чистые функции для преобразования, фильтрации и комбинирования потоков данных.
  • Subject — особый тип Observable, который одновременно является и Observer. Позволяет мультикастировать (раздавать) значения нескольким подписчикам.

Популярные операторы RxJS

Операторы — сердце RxJS. Они позволяют обрабатывать потоки данных декларативно. Рассмотрим несколько часто используемых:

  • map — преобразует каждое значение потока по заданной функции.
  • filter — пропускает только те значения, которые удовлетворяют условию.
  • mergeMap — проецирует каждое значение на Observable и объединяет результаты в один поток.
  • debounceTime — задерживает выдачу значений на указанное время (полезно для поисковых строк).
  • catchError — перехватывает ошибки в потоке и возвращает запасной Observable.

Пример использования операторов для обработки кликов:

import { fromEvent } from 'rxjs';
import { map, filter, debounceTime } from 'rxjs/operators';

const clicks = fromEvent(document, 'click');

clicks.pipe(
  debounceTime(300),
  map((event: MouseEvent) => ({
    x: event.clientX,
    y: event.clientY
  })),
  filter(pos => pos.x > 100)
).subscribe(pos => {
  console.log('Клик с координатами:', pos);
});

Практический пример: реактивная форма поиска

Рассмотрим типовую задачу — реализацию поиска с автодополнением. С RxJS это делается элегантно и без вложенных колбэков:

import { fromEvent } from 'rxjs';
import { map, debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';

const searchInput = document.getElementById('search') as HTMLInputElement;

const search$ = fromEvent(searchInput, 'input').pipe(
  map(event => (event.target as HTMLInputElement).value),
  debounceTime(400),
  distinctUntilChanged(),
  switchMap(query => fetchSearchResults(query)) // предполагаемая функция запроса
);

search$.subscribe(results => {
  console.log('Результаты поиска:', results);
});

Здесь debounceTime предотвращает частые запросы, distinctUntilChanged игнорирует повторяющиеся значения, а switchMap автоматически отменяет предыдущий запрос, если пользователь ввёл новый текст.

Работа с ошибками и завершением потоков

Ре

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