[Fixed] How to subscribe to a chain of Observables that contains a Promise

Issue

I had a nested Observable situation, and after some research I found that it’s best to use RxJS switchMap.

For my case the first observable contains a Promise, so I have to await the first subscription result before it’s passed to the second observable. Now the second Observable is not being subscribed to and is returning an Observable instead of subscribing to its results.

firstObservable(x) {
  return this.productService.getProduct(x).pipe(
    map(async result => {
       this.productObject = {...result};
       let timeVariable = await 
       this.distanceMatrixService.getTime(this.productObject, this.currentLocation);
       return this.productObject;
    })
}

async secondObservable(passedProductObject) {    
  const productObject = await passedProductObject;
  return this.productService.getProductsByShop(productObject.store_id).pipe(
    map(result => {
      ////STUFF that depends on the timeVariable 
    }));
} 

chainingObservables(x) {
  return this.firstObservable(x).pipe(
  switchMap(async x => this.secondObservable(x)));
}

this.chainingObservables(this.passedData).subscribe(res => {
 console.log("result", res);
})

result Observable {_isScalar: false, source: Observable, operator: MapOperator}

Any suggestion would be appreciated.

Solution

You could use RxJS from function to convert the promise to an observable. After that a couple of switchMaps with map ought to suffice your requirement.

Try the following

this.productService.getProduct(x).pipe(
  map(result => ({...result})),
  switchMap(productObject => 
    from(this.distanceMatrixService.getTime(productObject, this.currentLocation)).pipe(
      map(timeVariable => ({
        productObject: productObject,
        timeVariable: timeVariable
      }))
    )
  ),
  switchMap(({productObject, timeVariable}) =>
    this.productService.getProductsByShop(productObject.store_id).pipe(
      map(result => {
        // stuff that depends on `timeVariable`
      })
    )
  )
).subscribe(
  res => {
    console.log("result", res);
  },
  error => {
    // handle error
  }
);

Leave a Reply

(*) Required, Your email will not be published