I have spent 6 hours already trying to figure out how to do this in NodeJS.
I am using NodeJS with Express and MongoDB.
I have a database that has two collections viz. Listings and Categories. Each listing has a "category" which is an ID that maps to a category inside the Categories collection.
What I want to do is, fetch all the listings, then loop through all of them, and get the category title from the Categories collection using the category id.
This is what I had for getting all the listings:
const listings_raw = [];
await db.collection("listings").find().forEach(listing => listings_raw.push(listing));
The code above works fine. The trouble I am having is with this:
const listings = [];
listings_raw.forEach(async listing => {
const category_id = listing.category;
const category_title = await db.collection('categories').findOne({_id: objectId(category_id)});
listing.category_title = category_title;
listings.push(listing);
});
response.send(listings);
The response.send(listings);
gets executed before the listings_raw.forEach
completes.
I want to send the data only after all listings have been populated with the category titles.
After spending 6 hours, I have come up with the following hack which I am sure is nasty!
const listings_raw = [];
const em = new events.EventEmitter();
await db.collection("listings").find().forEach(listing => listings_raw.push(listing));
const listings = [];
let counter = 0;
listings_raw.forEach(async (listing) => {
const category_id = listing.category;
const category = await db.collection('categories').findOne({_id: objectId(category_id)});
listing.category_title = category.title;
listings.push(listing);
if (counter === listings_raw.length - 1) {
em.emit('listings:processing:done');
}
counter++;
});
em.on('listings:processing:done', () => {
response.send(listings);
});
Please, can someone explain or guide me on how this should be done in JavaScript?
Basically, I am not able to figure out how to know if all promises have been resolved or not.
Thank you!