How to handle for promise inside a piped map
Observables can be seen as a layer up to promises, why don't you use your promise this way ? like this :
let getDataFromJson(payloadData){
return from(EventImporterJSON.getFromJSON(payloadData());
}
return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(
map(document=>document.payload.data),
switchMap( payloadData=> getDataFromJson(payloadData)))
.subscribe(result=>{
//final result
});
1 pipe your first observable with map just to simplify your returner value
2 switchMap to another observable which will be your promise as an Observable ( with the "from" operator);
The map operator is made for improve result in synchronous and "pure" way like return only few properties of an object or filter a data, here you want to chain two async operation so I suggest you to keep it in a rx approach
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 also use async - await
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 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 the 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