BACK
Уроки22. Higher-Order Observable
Уроки · 22

22. Higher-Order Observable

Когда значение становится потоком

До этого мы преобразовывали значения в другие значения. Но в реальной жизни часто бывает: одно значение должно превратиться в асинхронную работу. Например:

  • id пользователя → HTTP-запрос за этим пользователем.
  • Клик → отправка формы.
  • Текст поиска → запрос к поисковому API.

Если мы внутри map вернём Observable, тип станет Observable<Observable<T>> — «поток потоков». Это и называют higher-order Observable (поток высшего порядка).

Проблема

Подписавшись на такой поток, мы получим не данные, а другой Observable. Чтобы добраться до значений, придётся подписаться ещё раз — внутри подписки. Это работает, но плохо: нет отмены, нет нормального управления порядком, легко получить утечки.

Куда мы движемся

Дальше мы изучим четыре flattening-операторы (от англ. flatten — «разгладить, выровнять»), которые решают эту проблему по-разному: mergeMap, concatMap, switchMap, exhaustMap. Каждый из них берёт значение, создаёт внутренний Observable и автоматически подписывается на него. Разница — в том, как они управляют порядком и отменой.

Учебная задача

В этом уроке мы намеренно делаем «плохо» — подписка внутри подписки. Это нужно, чтобы вы увидели проблему собственными глазами. Дальше будем чинить.

Что нужно сделать

  1. В pipe добавьте map(id => of('User ' + id)). Заметьте: внутри map мы возвращаем Observable, а не строку.
  2. Внутри внешней подписки добавьте inner$.subscribe(user => console.log(user)) — это вторая, вложенная подписка.
  3. Ожидаемый вывод: User 1 → User 2.
Решение spoiler · click to reveal
const { of, map } = Rx;

const userIds$ = of(1, 2);

const requests$ = userIds$.pipe(
  map(id => of('User ' + id))
);

requests$.subscribe(inner$ => {
  inner$.subscribe(user => console.log(user));
});
script.ts // TypeScript
CONSOLE · Console Output
Нажмите на запуск, чтобы увидеть результат...