Please see the code below for reference.
export const listenToHotels = (hotelIds: string[]): Observable < Hotel[] > => {
return new Observable < Hotel[] > ((observer) => {
const hotels: any = [];
hotelIds.forEach((hotelId) => {
let roomingList: any;
return FirestoreCollectionReference.Hotels()
.doc(hotelId)
.onSnapshot(
(doc) => {
roomingList = {
hotelId: doc.id,
...doc.data()
}
as Hotel;
console.log(`roomingList`, roomingList);
hotels.push({
...roomingList
});
},
(error) => observer.error(error)
);
});
//Check for error handling
observer.next(hotels);
console.log('hotels', hotels);
});
};
As you can see I am trying to run a forEach on a hotelId Array and in that firestore listener is being executed. Now I want to save the response and push that into hotels array but it gives me an error object not extensible error. The thing is observer and console.log('hotels',hotels) run first because of promise being executed at later stage.
Please let me know how can I resolve this issue.
I think you could use map instead of forEach, because you could use await with map
example of using map and await: https://flaviocopes.com/javascript-async-await-array-map/
Check out forkJoin. It takes an array of Observables and subscribes to them at the same time.
This example is written in Angular but the operators should be identical as long as you're using a current version of rxjs.
map to a single Observable (mapCalls)forkJoin is then added as a wrapper to the arrayforkJoin. All of the objects will make the call.subscribe() will be runSo in your case:
calls. Each item is the Observable logic you postedforkJoin(calls).subscribe() to make all the callsexport const listenToHotels = (hotelIds: string[]): Observable<Hotel[]> => {
const hotelsObservable = hotelIds.map((hotelId) => {
let roomingList: any;
return new Observable<Hotel>((observerInside) => {
FirestoreCollectionReference.Hotels()
.doc(hotelId)
.onSnapshot(
(doc) => {
roomingList = { hotelId: doc.id, ...doc.data() } as Hotel;
observerInside.next(roomingList);
},
(error) => observerInside.error(error)
);
});
});
const combinedObservable = combineLatest(hotelsObservable);
return combinedObservable;
//Check for error handling
};
The issue was how I was handling the chained observables(Execution of promise is delayed than a normal code because they will be put in micro-queue first). They need to be handled using zip or combineLatest but latter is much better in this use case as we need the latest values for the observables.