为什么只显示 Angular 异步管道绑定中字符串的最后一个字符?

cha*_*r m 3 rxjs angular

组件.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>
Run Code Online (Sandbox Code Playgroud)

组件.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';
      })
    );
  }
Run Code Online (Sandbox Code Playgroud)

当这失败时,只显示字母 'd'('failed')。如果我将其更改为:

      catchError(err => {
        console.debug('login failed: %s', JSON.stringify(err));
        return '123';
      })
Run Code Online (Sandbox Code Playgroud)

它显示 3。

Rea*_*lar 6

catchError()运营商期望的回调函数返回一个可观察的。我不确定它为什么呈现,3但很可能字符串被转换为一个可观察的数组,该数组按顺序发出每个字符。

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');
      })
Run Code Online (Sandbox Code Playgroud)

https://www.learnrxjs.io/operators/error_handling/catch.html

async在模板中使用管道时。请记住,如果 DOM 被上级改变,它将调用subscribe*ngIf。因此,如果 observable 来自 HTTP 请求,则添加一个shareReplay(1)运算符并仅在模板中使用相同的对象引用。