Как стать автором
Обновить

Комментарии 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>

Супер, ещё один способ использования 👍

Зарегистрируйтесь на Хабре, чтобы оставить комментарий