【问题标题】:Using Angular Async Pipe to Subscribe to Observable使用 Angular 异步管道订阅 Observable
【发布时间】:2020-11-13 17:27:01
【问题描述】:

我在我的 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() 方法,但使用异步管道处理组件视图中的订阅?

【问题讨论】:

    标签: angular asynchronous ionic-framework rxjs-observables


    【解决方案1】:

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

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

    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$ 变量。

    【讨论】:

    • 这在某种程度上有效,但仍然给了我一些意想不到的结果。请看我上面的更新。
    • @Rey: (user | async ) as user 不正确。插值可能会错误地使用可观察对象而不是通知。使用答案中显示的美元或使用不同的名称:(user | async ) as userDetails
    • 好的,明白了。实际上,从您更新的答案中,我意识到我缺少的是pipe()。那是关键的缺失部分。非常感谢,@Michael D。
    猜你喜欢
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 2019-05-06
    • 2017-11-30
    • 2021-06-09
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    相关资源
    最近更新 更多