Модуль 4 · урок 8 з 13
Subjects
Subject — це одночасно потік і спосіб у нього надсилати. Саме він перетворює
RxJS з інструменту читання даних на інструмент керування станом. У таблиці ліда згадані
BehaviorSubject і ReplaySubject — розберемо всі чотири, щоб
різниця була очевидною.
Subject: і мікрофон, і динамік
import { Subject } from 'rxjs';
const refresh$ = new Subject<void>();
refresh$.subscribe(() => console.log('оновлюємось'));
refresh$.next(); // сам штовхаєш значення в потік
На відміну від of чи http.get, Subject гарячий: він живе
сам по собі, а підписники отримують лише те, що прийшло після їхньої підписки.
Підписався пізно — попереднє пропустив.
Чотири види
BehaviorSubject — стандарт для стану
import { BehaviorSubject } from 'rxjs';
private readonly _filters = new BehaviorSubject<Filters>({ status: 'all', query: '' });
readonly filters$ = this._filters.asObservable(); // назовні лише для читання
get filters(): Filters {
return this._filters.value; // поточне значення без підписки
}
setStatus(status: TaskStatus | 'all'): void {
this._filters.next({ ...this._filters.value, status }); // незмінне оновлення
}
Три причини, чому саме він:
- Завжди має значення — початкове задається в конструкторі, тож підписник ніколи не побачить порожнечі.
- Новий підписник одразу отримує поточне — компонент, який відкрився пізніше, бачить актуальний стан, а не чекає наступної зміни.
- Значення можна прочитати синхронно через
.value— зручно, коли треба щось порахувати в обробнику події.
Приватний Subject, публічний Observable
// ❌ так будь-хто ззовні може штовхнути що завгодно
readonly tasks$ = new BehaviorSubject<Task[]>([]);
// ✅ так змінювати можна лише через методи сервісу
private readonly _tasks = new BehaviorSubject<Task[]>([]);
readonly tasks$ = this._tasks.asObservable();
Це той самий принцип інкапсуляції, що й з signal і asReadonly()
з модуля 2. Зовні — контракт на читання, всередині — контрольовані зміни. Наступний урок
цілком побудований на цьому патерні.
Коли який брати
| Вид | Що бачить пізній підписник | Типовий випадок |
|---|---|---|
Subject | Нічого з минулого | Події: «оновити», «закрити модалку» |
BehaviorSubject | Поточне значення | Стан: фільтри, дані, поточний користувач |
ReplaySubject(n) | Останні n значень | Історія, лог подій, кеш кількох останніх |
AsyncSubject | Лише останнє, після complete | Майже ніколи |
У сучасному Angular для локального стану компонента здебільшого беруть signal.
BehaviorSubject лишається доречним там, де стан треба комбінувати з іншими
потоками — з debounceTime, switchMap, HTTP. Тобто в сервісах-сторах,
де живе асинхронність. У таблиці ліда згаданий саме він, тож у практиці модуля робимо на ньому —
а в уроці 12 подивимось, як їх зшивати між собою.