【问题标题】:Creating an observable from multiple observable values从多个可观察值创建可观察值
【发布时间】:2020-04-02 15:18:49
【问题描述】:

在我的一个组件中,我需要遍历一组 id 并为每个组件进行 API 调用。 api 调用返回 observables,目前我只是订阅循环中的每一个并将其值添加到数组中。我不认为这很好,因为我正在单独订阅每个电话。有没有办法我可以使用mergeMap 或类似的东西来创建循环中所有组合值的可观察值?

这样我就可以订阅一个 observable(或使用 HTML 中的异步管道)而不是多个?

这是我的控制器代码:

export class GraphTablesComponent implements OnInit {

  @Input() meta: any;
  @Input() entityId: number;
  kpiData: Array<any> = [];

  constructor(
    private apiService: ApiService
  ) { }

  ngOnInit() {
    this.getKpiData();
  }

  private getKpiData(): void {
    for (const m of this.meta) {
      this.apiService.post(`${Endpoints.KPIS}execute/${m._bid}/${this.entityId}`, {}).subscribe(d => this.kpiData.push(d));
    }
  }
}

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    你可以使用ForkJoin来实现

    private getKpiData(): void {
        let requestArray = [];
    
        for (const m of this.meta) {
          requestArray.push(this.apiService.post(`${Endpoints.KPIS}execute/${m._bid}/${this.entityId}`, {}))
        }
    
        forkJoin(requestArray).subscribe(data => {
          this.response1 = data[0];
          this.response2 = data[1];
        });
    }
    

    如果你想直接在模板中添加,

    .ts

    this.data$ =  forkJoin(requestArray)
    

    .html

    <ng-container *ngIf="data$ | async; let data">
       {{data | json}}
    </ng-container>
    

    【讨论】:

    • 我可以只做this.data = forkJoin(requestArray); 然后在 HTML 中订阅它吗?
    • 不,您必须订阅。 Forkjoin 返回 observable。 forkJoin(requestArray).subscribe(data =&gt; { Could I just do this.data = data ...
    • 你可以这样做。数据 |异步提供数据转换成你想要的格式
    • 是的,这是处理 observables 的另一种方式。但是
    • 让我补充一下,使用地图功能会更好const requestArray = this.meta.map(m =&gt; this.apiService.post(${Endpoints.KPIS}execute/${m._bid}/${this.entityId}, {}))
    【解决方案2】:

    您可以使用concat。它将所有的 observables 捆绑在一起并一个接一个地生成(这意味着它也保留了顺序):

    因为是我自己用的,所以可以举个简单的例子:

    服务方式:

      /**
       * Makes a chain of requests one by one
       * type
       * @param {any[]} data
       * @return {Observable<any>}
       */
      generateTexts(data: any[]): Observable<any> {
    
        return concat(
          ...data.map(entry => this.httpClient.post(this.url, this.getRequestBody(entry))
        );
      }
    

    接收值的 Observable:

    this.apiService.generateTexts(data).subscribe((response) => {
      // Handle response, this will be called multiple times as long as
      // requests are made
      // 'reponse' contains 1 request response
    });
    

    【讨论】:

    • forkJoin 在它的最终响应中也保留了顺序,仅供参考。主要区别在于 concat 顺序执行并且 forkJoin 是并行的,并且 concat 会发出多次,而 forkJoin 会发出一次所有值。
    • 是的,这取决于用例。在我的情况下,服务器性能不允许同时做事
    猜你喜欢
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    • 2021-04-13
    • 2019-10-15
    相关资源
    最近更新 更多