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?
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.
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.
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 mergeMap
s project function an it will work fine.
Typically, you don't need to use multiple await
s 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With