AvinashK
AvinashK

Reputation: 3423

Correct way of passing data from one observable to other

I have two HTTP APIs -

  1. Gets a list of tableNames
  2. Gets a list of metadata

I am working on an Angular 5 application where the metadata (from 2nd API) before being displayed has to be modified by using the table names (from 1st API).

Therefore, I see the task as follows-
I have two observables. The first observable connects to the tableNames API and brings tableNames. The second observable connects to the metadata API, brings metadata and modifies the metadata according to the tableNames API output. I would like to keep the final product (modified metadata) as an observable which the angular application can subscribe to.

Currently, the code looks currently looks something like below-

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));

I didn't feel good about the code since I was assuming synchrony between two async operations. The doubt was proved right after reading this article. So, using the approach suggested in the article, I changed the code to give tableNames as a parameter to generate new Observables and use switchMap (I could have used concatMap/flatMap but switchMap suited my requirements).

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

Is this the correct way to go about this task or are there other better techniques to achieve this?

Upvotes: 2

Views: 1095

Answers (1)

cartant
cartant

Reputation: 58400

If getTablesNamesObservable and getOperatorMetadata are independent, it would make more sense to use combineLatest:

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

Then modifyMetadata will be called whenever either observable emits a value.

By using switchMap, you unsubscribe and resubscribe to the observable returned by getOperatorMetadata whenever the observable returned by getTablesNamesObservable emits. And if they are independent - that is, getOperatorMetadata does not need to be passed the table names - doing do seems unnecessary.

If the observables each emit only a single value - or if you want only the last-emitted value of each - use forkJoin instead of combineLatest.

Upvotes: 2

Related Questions