如何在 运行 初始化代码之前等待模板中的可观察对象(使用异步管道)被订阅?

How to wait for observables in template (using async pipe) to be subscribed to before running initialisation code?

我有一个 HTTP 服务,当给定的项目 ID 传递给它时,该服务 returns 一些信息。这是通过 Subject 完成的,它在 ngOnInit 方法中接收了第一条数据。

然后我使用 async 管道显示 HTML 中服务返回的数据。

我的问题是 async 管道在我用第一个项目 ID 调用 selections.next 时没有订阅可观察对象 - 因此这个在初始化时没有显示。

如何才能等到 async 管道订阅了 Observable 之后才能将第一条数据发送给主题以开始第一个 HTTP 请求?

我尝试了不同的 lifecycle hooks,但 none 似乎有效。

import { Component, OnInit } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { Subject } from "rxjs/Subject";

import { ExampleService } from "./example.service";

import "rxjs/add/operator/switchMap";

@Component({
  template: `
    <div>
      <div *ngFor="let time of times | async">{{ time }}</div>
    </div>
  `,
})
export class ExampleComponent implements OnInit {

  times: Observable<string[]>;

  constructor(
    private exampleService: ExampleService
  ) { }

  ngOnInit() {

    var itemIds = new Subject<number>();

    this.times = itemIds
      .switchMap(itemId => this.exampleService.getData(itemId))
      .map(data => this.calculateTimes(data));

    // Pass an item ID to the subject.
    // This is done periodically as well as
    // on init.
    itemIds.next(10);
  }

  calculateTimes(data: string[]) {
    /*
     * Some processing code.
    */

    return data;
  }
}

使用行为主题而不是主题。

行为主题保存它的最后一个值并将其发送给订阅的新订阅者。

import { BehaviorSubject } from "rxjs/BehaviorSubject";


var itemIds = new BehaviorSubject<number>(null);

行为主体需要用一个值初始化。当您不知道您的价值或您的订阅者是否会先到达时,它的存在就是为了解决这个计时问题。

如果您想避免重复调用,您可以设置本地存储模式:

times: BehaviorSubject<string[]> = new BehaviorSubject<string[]>();


var itemIds = new Subject<number>();

itemIds.switchMap(itemId => this.exampleService.getData(itemId))
    .map(data => this.calculateTimes(data)).subscribe(this.times);

这样,您对 http 调用的唯一订阅者就是您在模板中订阅的行为主题。