Reputation: 8336
component.html:
<div *ngIf="!isWaiting">
<h2>LOGIN</h2>
<p>{{ message | async }}</p>
<div *ngIf="!(isLoggedIn | async)">
<button (click)="login()">{{'StrLogin' | translate}}</button>
</div>
<div *ngIf="(isLoggedIn | async)">
<button (click)="logout()">{{'StrLogout' | translate}}</button>
</div>
</div>
<div *ngIf="isWaiting">
<p>initializing</p>
</div>
component.ts
message: Observable<string>;
login(name : string, password : string): void {
this.message = this.tokenService.login(name, password)
.pipe(
map((token) => {
console.debug('login succeeded: %s', JSON.stringify(token));
return 'success';
}),
catchError(err => {
console.debug('login failed: %s', JSON.stringify(err));
return 'failed';
})
);
}
When this fails only the letter 'd' (of the 'failed') is displayed. If I change it to:
catchError(err => {
console.debug('login failed: %s', JSON.stringify(err));
return '123';
})
it displays 3.
Upvotes: 6
Views: 740
Reputation: 54771
The catchError()
operator expects the callback function to return an observable. I'm not sure why it renders 3
but most likely the string was converted into an observable array that emits each character in sequence.
https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/catchError.ts#L90
catchError(err => {
console.debug('login failed: %s', JSON.stringify(err));
return of('failed');
})
https://www.learnrxjs.io/operators/error_handling/catch.html
When using the async
pipe in templates. Keep in mind that it will call subscribe if the DOM is mutated by a *ngIf
higher up. So if the observable is sourced from an HTTP request, then add a shareReplay(1)
operator and only use the same object reference in the template.
Upvotes: 10