22. Higher-Order Observable
Когда значение становится потоком
До этого мы преобразовывали значения в другие значения. Но в реальной жизни часто бывает: одно значение должно превратиться в асинхронную работу. Например:
- id пользователя → HTTP-запрос за этим пользователем.
- Клик → отправка формы.
- Текст поиска → запрос к поисковому API.
Если мы внутри map вернём Observable, тип станет Observable<Observable<T>> — «поток потоков». Это и называют higher-order Observable (поток высшего порядка).
Проблема
Подписавшись на такой поток, мы получим не данные, а другой Observable. Чтобы добраться до значений, придётся подписаться ещё раз — внутри подписки. Это работает, но плохо: нет отмены, нет нормального управления порядком, легко получить утечки.
Куда мы движемся
Дальше мы изучим четыре flattening-операторы (от англ. flatten — «разгладить, выровнять»), которые решают эту проблему по-разному: mergeMap, concatMap, switchMap, exhaustMap. Каждый из них берёт значение, создаёт внутренний Observable и автоматически подписывается на него. Разница — в том, как они управляют порядком и отменой.
Учебная задача
В этом уроке мы намеренно делаем «плохо» — подписка внутри подписки. Это нужно, чтобы вы увидели проблему собственными глазами. Дальше будем чинить.
Что нужно сделать
- В
pipeдобавьтеmap(id => of('User ' + id)). Заметьте: внутриmapмы возвращаем Observable, а не строку. - Внутри внешней подписки добавьте
inner$.subscribe(user => console.log(user))— это вторая, вложенная подписка. - Ожидаемый вывод:
User 1 → User 2.
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));
});