Reputation: 397
i'm building a crud app for a project, people can add view and delete entries, i'm using nodejs, js and fireabse for this. i have such a firestore database structure:
entries:
--entry id
--entry data
users:
--user id
--user email (query)
-- my entries (collection)
-- entries id
--entry id
now i want to display all users entries, so i created this module.exports function:
module.exports = {
//get all the users entries from database with passed in uid ('/dashboard')
getUserEntries: async uid => {
//get all his entries docs id from "myEntries" collection in an, array
const usersEntriesId = await db
.collection("users")
.doc(uid)
.collection("myEntries")
.get()
.then(entries => {
return entries.docs.map(entry => entry.data().entry);
})
.catch(err => console.log(err));
console.log(usersEntriesId); //works fine, logs array with ids
const userEntriesDocs = usersEntriesId.map(async id => {
const entry = await db
.collection("entries")
.doc(id)
.get()
.then(entry => {
return entry.data();
});
console.log("hello:", entry); //works fine returns logs entry data
return entry;
});
console.log("hello1: ", userEntriesDocs); //doesnt work i get "hello1: [ Promise { <pending> },
// Promise { <pending> },
//Promise { <pending> } ]"
//i got three entries, that's why i get 3 times "Promise { <pending> }"
}
};
so how do i resolve that?
Thanks
Upvotes: 1
Views: 7864
Reputation: 23705
well, async
function returns Promise
, it how they works under the hood. If there was no .map
you could just await
on that function or use it as arbitrary Promise
with .then()
and .catch
. But since there is array of Promise
you need Promise.all
to wait until all are resolved.
const userEntriesDocs = await Promise.all(usersEntriesId.map(async id => {
....
);
Beware: unlike .allSettled
, .all()
will fail immediately if any of subsequent Promise
fails. So if for any reason you want to have data from those requests that succeeded, you need more complex logic.
As an alternative you may go through loop manually:
const userEntriesDocs = [];
for(const docPromise of userEntriesId.map(.....)) {
userEntriesDocs.push(await docPromise);
}
But to me await Promise.all[...]
is more readable.
Also I highlight there is array of Promises(requests have already been sent). If you try sending requests inside the loop like
const userEntriesDocs = [];
for(const id of userEntriesId) {
userEntriesDocs.push(await db
.collection("entries")
.doc(id)
.get()
.then(entry => {
return entry.data();
})
);
}
you will find that requests are going strictly one-by-one, not in parallel. That will require much more time to process the list.
Upvotes: 4