Модуль 4 · урок 4 з 13
Сімейство *Map
Це найважливіший урок модуля й найчастіше питання на співбесідах. Усі чотири оператори роблять одне: беруть значення, створюють з нього новий потік і підмішують його результати у вихідний. Різниця тільки в одному — що робити, якщо нове значення прийшло, поки попередній внутрішній потік ще не завершився.
Задача, яку вони вирішують
// ❌ так не працює: map поверне Observable всередині Observable
query$.pipe(
map(q => this.api.search(q)), // Observable<Observable<Task[]>>
).subscribe(result => …); // result — це потік, а не дані
// ✅ *Map розгортає вкладений потік
query$.pipe(
switchMap(q => this.api.search(q)), // Observable<Task[]>
).subscribe(tasks => …);
Чотири стратегії
switchMap — скасувати попереднє
searchQuery$.pipe(
switchMap(q => this.api.search(q)),
);
Коли: пошук, фільтри, завантаження деталей при зміні вибраного елемента — усе, де потрібен лише останній результат.
Чому саме він: користувач набирає «kyi», потім «kyiv». Запит по «kyi» більше не
потрібен — гірше того, він може повернутись пізніше за запит по «kyiv» і перезаписати
правильний результат неправильним. switchMap скасовує попередню підписку й
знімає цю проблему повністю.
mergeMap — усе паралельно
selectedIds$.pipe(
mergeMap(id => this.api.delete(id)), // видалити всі відмічені одночасно
);
Коли: незалежні операції, де порядок не має значення й скасовувати нічого не треба.
Обережно: без обмеження одночасності можна вистрілити сотню запитів разом.
Другим аргументом задається ліміт: mergeMap(fn, 3).
concatMap — строго по черзі
saveActions$.pipe(
concatMap(action => this.api.save(action)), // наступний старт лише після завершення попереднього
);
Коли: порядок критичний — послідовні збереження, черга дій, синхронізація офлайн-змін. Мінус очевидний: якщо один запит зависне, черга стане.
exhaustMap — ігнорувати, поки зайнятий
fromEvent(saveButton, 'click').pipe(
exhaustMap(() => this.api.save(form.value)), // подвійний клік не створить другий запит
);
Коли: захист від повторних натискань, логін, будь-яка дія, яку не можна запускати двічі. Це найелегантніше рішення проблеми «користувач клікнув кнопку тричі».
Як вибрати за десять секунд
| Питання | Оператор | Типовий випадок |
|---|---|---|
| Потрібен лише останній результат? | switchMap | Пошук, фільтри, деталі вибраного |
| Усі важливі, порядок байдужий? | mergeMap | Масові незалежні дії |
| Усі важливі, порядок критичний? | concatMap | Черга збережень |
| Поки зайнятий — ігноруємо нові? | exhaustMap | Кнопка «Зберегти», логін |
switchMap для збереження чи видалення. Якщо користувач швидко натисне двічі,
перший запит скасується — і сервер може отримати лише другий. Для дій, які змінюють дані,
бери concatMap або exhaustMap. Просте правило:
switchMap — для читання, concat/exhaust — для запису.