0

How can I use promise.all with this function :

function getUsersGroups(users, req) {
  users.forEach(function(user) {
    user.groups = [];

    db.collection("groups")
      .find({ "users._id": String(user._id) })
      .toArray(function(err, docs) {
          user.groups = docs;
      });
  });

  return users;
}

I don't know how to do , thank you.

PS : the users array doesn't get actualized with the docs (they console log ok).

Thi is my second try :

function getUsersGroups(users, req) {
  users.forEach(
    (user, index, array) => (
      array[index].user =[]
      array[index].user.groups = myApiCall(user))
  );

  function myApiCall(user) {
    db.collection("groups")
      .find({ "users._id": String(user._id) })
      .toArray(function(err, docs) {
        console.log(docs);
        return docs;
      });
  }

  return users;
}



  array[index].user.groups = myApiCall(user))
      ^^^^^

SyntaxError: Unexpected identifier

Edit :

So finally, I'm using this function, like Ashish said ( it is getting all of the groups a user is in, and updating the users model) :

async function getUsersGroups(users, req) {
  await Promise.all(users.map(user => {
    return db.collection("groups")
      .find({ "users._id": String(user._id) })
      .toArray()
      .then(group => {
        user.groups = group;
      })
  }));

  return users;
}

And I am calling like this inside of another node.js function :

 getUsersGroups(docs, req)
          .then(users => {
            res.send(users);
          })
          .catch(error => {
            // if you have an error
          });

Thank you a lot !

harmonius cool
  • 337
  • 1
  • 2
  • 23

2 Answers2

0
async function getUsersGroups(users, req) {
  await Promise.all(users.map(user => {
    return db.collection("groups")
      .find({ "users._id": String(user._id) })
      .toArray()
      .then(group => {
        user.groups = group;
      })
  }));

  return users;
}

Hope this helps

Ashish Modi
  • 7,529
  • 2
  • 20
  • 35
0

Looking at the documentation for toArray, it returns a Promise if the callback is not specified. We can then use .map instead of .forEach to produce an array of promises, which we can then pass to Promise.all:

function getUsersGroups(users, req) {
  const promises = users.map(function(user) {
    user.groups = []
    return db
      .collection("groups")
      .find({ "users._id": String(user._id) })
      .toArray()
      .then(groups => {
        user.groups = groups
      })
  });

  return Promise.all(promises);
}

Notice that this mutates the user objects. That is, whatever users you pass in to the function will be modified with the groups field getting set.

cbr
  • 12,563
  • 3
  • 38
  • 63
  • Thanks a lot, your function is working, but when I'm calling it from another function, getUsersGroups(docs, req); is empty, while console.log(groups) says it is populated when inside of getUsersGroups(). – harmonius cool Jan 06 '20 at 20:08
  • How do I call this function ? – harmonius cool Jan 06 '20 at 20:13
  • I'm trying to call it like this : getUsersGroups(docs, req) .then(result => { console.log(result); res.send(result); }) .catch(error => { // if you have an error }); with no luck – harmonius cool Jan 06 '20 at 20:18
  • Thank you a lot for your excellent answer , I've finally used the Ashish answer , and called the function like this getUsersGroups(docs, req) .then(result => { console.log(result); res.send(result); }) .catch(error => { // if you have an error }); but I guess that your answer is also working . – harmonius cool Jan 06 '20 at 20:22