正确的方式将数据从一个可观察的对象传递到另一个

时间:2018-07-04 23:25:14

标签: angular asynchronous rxjs observable

我有两个HTTP API-

  1. 获取表名列表
  2. 获取元数据列表

我正在使用Angular 5应用程序,其中必须通过使用表名(来自第一个API)来修改显示前的元数据(来自第二个API)。

因此,我看到的任务如下-
我有两个观察点。第一个可观察的对象连接到tableNames API并带来tableNames。第二个可观察对象连接到metadata API,根据tableNames API输出输出元数据并修改元数据。我希望最终产品(修改后的元数据)保持可观察的角度,角度应用程序可以订阅。

当前,该代码当前看起来如下所示-

private tablesNames: ReadonlyArray<String> | undefined;

this.getTablesNamesObservable().subscribe(
      tablesNames => { this.tablesNames = tablesNames; }
    );

// modify metadata uses tableNames to modify the metadata
this.modifiedMetadataObservable = this.metadataService.getOperatorMetadata()
                                      .map(metadata => this.modifyMetadata(metadata));

由于我假设两个异步操作之间是同步的,所以我对代码并不满意。阅读this article后就证明了这种怀疑。因此,使用本文中建议的方法,我更改了代码,将tableNames作为参数来生成新的Observable并使用switchMap(我本可以使用concatMap / flatMap,但switchMap适合我的要求)。

this.getTablesNamesObservable().switchMap(
      tableNames =>{this.metadataService.getOperatorMetadata()
                        .map(metadata => this.modifyMetadata(metadata, tableNames));}
      );

这是执行此任务的正确方法,还是还有其他更好的技术来实现这一目标?

1 个答案:

答案 0 :(得分:2)

如果getTablesNamesObservablegetOperatorMetadata是独立的,则使用combineLatest更有意义:

Observable.combineLatest(
  this.getTablesNamesObservable(),
  this.metadataService.getOperatorMetadata()
).map(([tableNames, metadata]) => this.modifyMetadata(metadata, tableNames));

然后,只要任一可观察对象发出一个值,就会调用modifyMetadata

通过使用switchMap,您可以退订并重新订阅getOperatorMetadata返回的可观察对象。而且,如果它们是独立的,即不需要传递getTablesNamesObservable表名,那么这样做似乎是不必要的。

如果每个可观察对象仅发出一个值-或者如果您只希望每个对象最后发出的值-请使用getOperatorMetadata而不是forkJoin