Return does wait for two awaits in the same function. JavaSript

81 views Asked by At

Hey guys Im new to nodeJS and mongoDb. So I am having some problems with this code, that seem to work for others people, as it is part of a tutorial, but not for me. The problem is in the function 'followThisUser', I have verified that the return, does not wait until 'following' and 'followed' vars are assigned a value. And it just return them as undefined. If someone could please help me understand why this is happening and also give me a solution I would be very greatfull.

async function followThisUser(indentity_user_id, user_id) {
  var following = await Follow.findOne({
    user: indentity_user_id,
    followed: user_id
  }).exec((err, follow) => {
    if (err) return handleError(err);
    return follow;
  });

  var followed = await Follow.findOne({
    user: user_id,
    followed: indentity_user_id
  }).exec((err, follow) => {
    if (err) return handleError(err);
    return follow;
  })

  return {
    following,
    followed
  }
}

function getUser(req, res) {
  var userId = req.params.id

  User.findById(userId, (err, user) => {
    if (err) return res.status(500).send({
      message: 'Error en la petición'
    })
    if (!user) return res.status(404).send({
      message: 'Error el usuario no existe'
    })

    followThisUser(req.user.sub, userId).then((value) => {
      user.password = undefined;
      return res.status(200).send({
        user,
        value
      })
    })
  })
}
2

There are 2 answers

0
Codebling On BEST ANSWER

It looks like there is some confusion here regarding the use of await here.

My answer to this Mongoose question may help you understand how await, Promises and Node-style callbacks work together.

The problem

findOne is an asynchronous function.

There are 3 ways to get notified that it is ready to return a value: 1. Take the Promise it returns and use .then()

Follow.findOne({})
  .then(data => {doSomething()});
  1. Give findOne a callback
Follow.findOne({}, (err, data) => {doSomething()});
  1. Use .exec(). this operates like one of the two cases above

You can also use await with the Promise-form , instead of .then(), e.g.

await Follow.findOne({});
doSomething();

The problem is that you are both passing a callback and also awaiting a result.

Solution

Don't pass callbacks to .exec()

  var following = await Follow.findOne({
    user: indentity_user_id,
    followed: user_id
  }).exec();

  var followed = await Follow.findOne({
    user: user_id,
    followed: indentity_user_id
  }).exec();
0
jfriend00 On

First off, await only does something useful if you are awaiting a promise.

Second, in mongoose, model.findOne().exec() ONLY returns a promise if you do NOT pass a callback to .exec(). If you pass a callback (as you are doing), it communicates completion or error via that callback and there is no promise returned. Thus your await statements are not doing anything.

So, to get promises back from .exec() and give the await a chance to do something useful, remove the callback from .exec().