Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle for promise inside a piped map

Tags:

I am definitely sure I am confused here so please any help is appreciated.

Here is my scenario:

I pull from Firestore a document:

return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(       map( document => {        })     ); 

All is fine up to here.

But inside the map I need a promise to resolve (or not)

For example:

return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(       map( document => {         // This is a promise the below part          const data = await EventImporterJSON.getFromJSON(document.payload.data())         return data       })     ); 

I understand that the await cannot happen there. I am very confused how to solve this, perhaps I have not worked long enough with observables and rxjs.

In the end what I am trying to achieve is:

Get the document. Map and process it but inside the process, I need to handle a promise.

I don't want to return that promise to the caller though.

Does this make sense?

Or have I structured this completely wrong?

like image 461
Jimmy Kane Avatar asked Dec 06 '18 10:12

Jimmy Kane


People also ask

How do you handle promises inside promises?

Here we need to first declare a Promise by using the Promise syntax, and we will be using the then() method for its execution and then inside that then() method we will create another promise by using the same Promise syntax as illustrated above, and then we will call our result of first inside that new Promise.

What is promise in RxJS?

the Promise can provide a single value, whereas the Observable is a stream of values (from 0 to multiple values), you can apply RxJS operators to the Observable to get a new tailored stream.


1 Answers

This is a typical use-case for mergeMap or concatMap:

return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(   mergeMap(document => {     // This is a promise the below part      return EventImporterJSON.getFromJSON(document.payload.data())   }) ); 

However, you can use async - await as well because operators such as mergeMap handle Observables, Promises, arrays, etc. the same way, so you can just return a Promise in mergeMaps project function an it will work fine.

Typically, you don't need to use multiple awaits in a single method because the more "Rx" way of doing things is chaining operators but if you want you can because async method returns a Promise and RxJS will handle it like any other Promise.

const delayedPromise = () => new Promise(resolve => {   setTimeout(() => resolve(), 1000); })  of('a').pipe(   mergeMap(async v => {     console.log(1);     await delayedPromise();     console.log(2);     await delayedPromise();     console.log(3);     await delayedPromise();     return v;   }) ).subscribe(console.log); // 1 // 2 // 3 // a  Live demo: https://stackblitz.com/edit/rxjs-3fujcs 
like image 151
martin Avatar answered Sep 21 '22 19:09

martin