Handle observable errors with async pipe in a reactive way

I am trying to implement direct observable streams to my template using async pipe, and handling errors as described in this S.O answer. Code is as follow :

export class MyClass {
  private myData$: Observable<any>;
  private hasError$: Observable<boolean>;

  constructor(private shared: SharedService) {
    this.myData$ = this.shared.data$;
    this.hasError$ = this.myData$.catch(err => Observable.of(true)).startWith(false);
  }

}

templateUrl: `
<div *ngFor="let elm of (myData$ | async)?.data">
...
</div>    
<div *ngIf="(hasError$ | async)" class="myDataErrorPlaceholder">
    <h3>Oooops ! An error occured.</h3>
</div>

`

No matter what I try, myDataErrorPlaceholder never gets hidden.

I've subscribed to my hasError$ observable for debug, and could see that the initial value from my startWith got broadcasted, but was immediately replaced by the data received by myData$. I can't really wrap my head around this. What causes such behaviour ? How can I implement direct error handling without having to subscribe manually to the Observable in my component ?

Upvotes: 1

Views: 1547

Answers (1)

Explosion Pills
Explosion Pills

Reputation: 191799

myData$ will still emit its values in spite of having .catch or .startWith. I think that the simplest solution for you would be to use .mapTo(false) instead to map all emissions to false. If there is an error, it will still emit true (and complete).

this.hasError$ = this.myData$.pipe(catchError(err => of(true)), mapTo(false));

Upvotes: 4

Related Questions