1

I have this function in javascript node

exports.getUserEmailByAccess = async (moduleType) => {
 let emailList = []
 const foundUsers = await Access.find({moduleType:moduleType})
 console.log(foundUsers);
 await foundUsers.forEach(access => {
 User.findById(access.userId)
 .then(foundUser => {
 console.log(foundUser.workerEmail);
 emailList.push(foundUser.workerEmail)
 })
 
 });
 console.log(emailList);
 return emailList
}

What I want is to push into emailList array by looping object array, the above approach results in an empty array,so I tried a different following way

exports.getUserEmailByAccess = async (moduleType) => {
 let emailList = []
 const foundUsers = await Access.find({moduleType:moduleType})
 console.log(foundUsers);
 await foundUsers.forEach(access => {
 const foundUser = User.findById(access.userId)
 console.log(foundUser.workerEmail);
 emailList.push(foundUser.workerEmail)
 
 });
 console.log(emailList);
 return emailList
 
}

By doing this , the array list is getting filled but with an [undefined]strong text value, I come from a humble python control structure background, Please can I know why I am not able to push data into array even after using async/await

asked Aug 24, 2021 at 10:51
3
  • does foundUsers.forEach return a Promise - if not, you can't await it ... I'm assuming that is NOT Array forEach, in which case, never use Array forEach with async/await, unless you REALLY know what you're doing - and even then, there's always better ways to do it Commented Aug 24, 2021 at 10:55
  • @Bravo is right, forEach doesn't wait for the promise to be resolved, instead you should use a for loop. Commented Aug 24, 2021 at 10:57
  • the answer depends if you can User.findById in parallel or in series Commented Aug 24, 2021 at 11:01

3 Answers 3

2

If the User.findById() returns a promise, I'd recommend using Promise.all() instead of individually running all promises using forEach to fetch documents of all foundUsers:

exports.getUserEmailByAccess = async (moduleType) => {
 const foundUsers = await Access.find({ moduleType: moduleType });
 console.log(foundUsers);
 const userDocs = await Promise.all(
 foundUsers.map((user) => User.findById(user.userId))
 );
 const emailList = userDocs.map((user) => user.workerEmail);
 // or alternatively
 // const emailList = userDocs.map(({workerEmail}) => workerEmail);
 console.log(emailList);
 return emailList;
};
answered Aug 24, 2021 at 11:24
Sign up to request clarification or add additional context in comments.

Comments

1

you can give try this

exports.getUserEmailByAccess = async (moduleType) => {
 let emailList = []
 const foundUsers = await Access.find({ moduleType: moduleType })
 console.log(foundUsers);
 await foundUsers.map(async access => {
 let result = await User.findById(access.userId);
 if (result) {
 emailList.push(foundUser.workerEmail)
 }
 });
 console.log(emailList);
 return emailList
}

UPDATED

await Promise.all(
 foundUsers.map(async access => {
 let result = await User.findById(access.userId);
 if (result) {
 emailList.push(foundUser.workerEmail)
 }
 })
])
console.log(emailList);
return emailList
answered Aug 24, 2021 at 10:57

3 Comments

map won't wait for the async function to be resolved, the emailList will remain empty.
Array map also doesn't return a Promise - so this is just as bad ... usually it's something like await Promise.all(array.map ..... if you want to do things parallel
Yes ,it still returns empty array
1

How are your Models related? I think you might do a populate here if the Access Model has the ObjectId of the User Model. Something like this:

const foundUsers = await Access.find({ moduleType: moduleType }).populate({
 path: 'users', // the name of the field which contains the userId
 select: '-__v' // fields to bring from database. Can add a (-) to NOT bring that field
})

The idea is that you specify all the fields that you need. Then when you receive the data, you can do something like:

foundUsers.users.email
answered Aug 24, 2021 at 11:29

1 Comment

"Can add a (-) to NOT bring that field", you can also specify that in your query using projections

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.