使用 Angular 异步管道订阅 Observable

Using Angular Async Pipe to Subscribe to Observable

我在 Angular/Ionic 应用程序的几个不同组件中成功订阅了一个 observable。但是,因为我手动这样做,这也意味着我需要手动取消订阅它们,我目前在 ngOnDestroy() 生命周期挂钩中这样做。

我的组件代码实现是这样的:

  getPlayerStats() {
    this.playerSubscription = this.mainService.getPlayerStats(this.username).subscribe(
      user => {
        this.user = user;
      },
      error => this.errorMsg = error
    );
  }

我的组件视图代码如下所示:

<ion-card *ngIf="user">
  ... display user info
</ion-card>

这里调用的服务方法如下所示:

  getPlayerStats(username: string) {
    const req = `users/stats/${username}`;
    return this.apiService.sendRequest(req);
  }

我想做的,但我很难开始工作,是使用 async 管道在我的 HTML 视图中进行订阅。那会更干净,因为那样我就不必那么冗长,也不必在我使用它的组件中手动订阅和取消订阅。我的理解是,正是出于这些原因,这也是处理这些情况的推荐方式。

该代码是什么样的?我试过了,但没用:

getPlayerStatus() {
  this.user = this.mainService.getPlayerStats(this.username);
}

在我的 HTML 视图中,我这样做了:

<ion-card *ngIf="user | async">
  ... display user info
</ion-card>

但正如我所说,这是行不通的。我需要在这里改变什么?如何调用服务 getPlayerStats() 方法,但使用异步管道处理组件视图中的订阅?

您可以尝试使用 *ngIf 指令的 as 签名。它还允许您使用单个 async 多次使用通知。假设可观察对象是一个 HTTP 调用,请记住每个 async 管道都会触发一个新请求,因为它是一个冷可观察对象。

通常的惯例是在可观察变量后加上美元符号。所以跟随它,控制器将是

user$: any;

getPlayerStatus() {
  this.user$ = this.mainService.getPlayerStats(this.username).pipe(
    catchError(error => {       // <-- HTTP error handling 
      this.errorMsg = error;
      return of(error);         // <-- return an observable from `catchError`
    }
  );
}

使用这个变量的模板是

<ng-container *ngIf="(user$ | async) as user">
  <ion-card>
    ... display user info
    {{ user | json }}
    {{ user.name }}
    ...
  </ion-card>
</ng-container>

这也是不言而喻的,但要使其正常工作,应该至少调用一次 getPlayerStatus() 函数来初始化 this.user$ 变量。