Комментарии 7
Первый случай с задержкой можно проще:
timer(3000).pipe(mapTo(throwError(...))
Второй - еще проще
race(this.first$, this.second$)
Я использовал materialize чуть ли не один раз в жизни. И вот тоже сейчас смотрю - пожалуй, мой случай можно было реализовать через defaultIfEmpty
, и было бы чуть проще.
Привет!
1) Да, это один из вариантов, почему бы и нет
Вероятно, кому-то будет удобен мой способ)
2) Все же race и merge работают совершенно по-разному, и с race не удастся воспроизвести то поведение, которое у меня в примере, например:
const subject1$ = new Subject();
const subject2$ = new Subject();
const result$ = race(
subject1$,
subject2$
).subscribe((x) => console.log(x));
subject1$.next(1);
subject2$.next(2);
subject1$.next(3);
subject2$.complete();
subject1$.next(4);
subject1$.complete();
subject1$.next(5);
Output:
// 1
// 3
// 4
Собственно, как и должен работать race - выигрывает в нашем случае subject1$, и следим далее мы только за ним (что заэмитилось первым, то и юзается)
очевидно, при complete subject2$ ничего не произойдет,
а это совсем не то, что я предлагала решить в статье)
Да, вы правы, а я был невнимателен. С race будет то же самое только в случае, если оба источника одноразовые (к примеру, запросы к серверу).
Пожалуй да, вариант с materialize самый простой. Даже удивительно, что в rxjs из коробки нет какого-то оператора для такого поведения.
Первый раз увидел эти операторы
Спасибо за полезную информацию
Оператор materialize() можно использовать для реализации показа лоадера/ошибки. Например, есть Observable, значение которого нужно отобразить в интерфейсе. Обычно в разметке это выглядит как {{ source$ | async }}
Но значение подгружается динамически с сервера, загрузка требует времени и может завершиться неуспешно. Хотелось бы показывать какой-то индикатор загрузки (спиннер или надпись "loading...").
Для решения этой задачи можно сделать {{ source$ | async as value else loadingTemplate }}, но проблема такого решения в том, что при получении ошибки пользователю будет показан бесконечный лоадер.
Хотелось бы останавливать лоадер и показывать ошибку если загрузка не удалась. Для обработки этих случаев идеально подходит объект Notification, который возвращает materialize()
Со стороны потребителя это может выглядеть и как кастомный аналог пайпа async, и как отдельный источник sourceStatus$, и как прямой байндинг на поля Notification.
Пример:
<ng-container source$ | async as notification else loading>
<span *ngIf="notification.hasValue">notification.value</span>
<span *ngIf="notification.kind === 'E'" class="error">Error: {{ notification.error }}</span>
</ng-container>
<ng-template #loading>
<span>Loading...</span>
</ng-template>
Зачем использовать materialize и dematerialize операторы и что такое Notification в RxJS?