Что такое Subject и какие виды Subject’ов существуют в RxJS?
Что такое Subject в RxJS?
Subject — это особый тип Observable
, который может мультикастить данные: т.е. отправлять значения сразу нескольким подписчикам.
Он объединяет свойства Observable (выдаёт значения) и Observer (можно передавать значения с помощью .next()
).
Особенности
- Вы сами инициируете передачу значений через
.next()
- Подписчики получают одинаковые данные
- Позволяет централизованно управлять потоком событий
Пример использования обычного Subject
import { Subject } from 'rxjs';
const subject = new Subject<string>();
subject.subscribe(val => console.log('Подписчик A:', val));
subject.subscribe(val => console.log('Подписчик B:', val));
subject.next('Привет');
// → Подписчик A: Привет
// → Подписчик B: Привет
Виды Subject’ов
RxJS предоставляет несколько видов Subject’ов, которые отличаются по поведению и способу хранения значений:
Тип | Сохраняет значение? | Что получает новый подписчик |
---|---|---|
Subject | Нет | Только новые значения после подписки |
BehaviorSubject | Да (только последнее) | Сразу получает последнее значение |
ReplaySubject | Да (все или часть) | Получает все/несколько прошлых значений |
AsyncSubject | Да (только финальное) | Получает только последнее, когда complete() |
BehaviorSubject
Используется, когда нужно, чтобы подписчики получали текущее значение сразу при подписке.
import { BehaviorSubject } from 'rxjs';
const behavior$ = new BehaviorSubject<number>(0);
behavior$.subscribe(val => console.log('A:', val)); // A: 0
behavior$.next(1); // A: 1
behavior$.subscribe(val => console.log('B:', val)); // B: 1
Идеально для хранения состояния (например, текущий пользователь, тема приложения и т.д.)
ReplaySubject
Позволяет «переиграть» прошлые значения для новых подписчиков.
import { ReplaySubject } from 'rxjs';
const replay$ = new ReplaySubject<number>(2); // хранит 2 последних значения
replay$.next(1);
replay$.next(2);
replay$.next(3);
replay$.subscribe(val => console.log('Подписчик:', val));
// → Подписчик: 2
// → Подписчик: 3
AsyncSubject
Выдаёт только последнее значение — только когда поток завершён (complete()
)
import { AsyncSubject } from 'rxjs';
const async$ = new AsyncSubject<number>();
async$.subscribe(val => console.log('Результат:', val));
async$.next(1);
async$.next(2);
async$.next(3);
async$.complete(); // → Результат: 3
Используется для отложенных значений, например, при однократном запросе данных
Когда использовать какой?
Сценарий | Subject |
---|---|
Поток событий (например, кнопки) | Subject |
Хранение состояния | BehaviorSubject |
История сообщений или логов | ReplaySubject |
Только результат после завершения операции | AsyncSubject |
Совет:
В Angular чаще всего используют BehaviorSubject
для управления состоянием компонентов и сервисов, так как он гарантирует актуальное значение при подписке.