0

Is there a way to call function that contains mongoose query inside other function, so other function will work properly?

My first function containing mongoose query:

getUserTags = (id) => {
    User.findById(id)
    .exec( (error, user) => {
      if (error) {
        return next(error);
      } else {       
        return user;
      }
    })
}

and my functions that needs to call that first function:

userTagToBookTagValues =  (id) => {
  const user = getUserTags(id);

  //I NEED THIS PART TO WORK AFTER getting data from getUserTags
  console.log(user);
  user.tags.forEach(tag => {
    console.log(tag)
  });
}

Is there a way so it works properly and user in second function will not be undefined?

Ismat Valiev
  • 135
  • 7
  • 1
    [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) Mongoose already supports 2 of the options covered there – callbacks and promises (although, not both in the same call, so each time you'll have you choose one). You'll need to extend that into how you define and call your own function(s) – `getUserTags(id).then(user => { ... })`, for example. – Jonathan Lonowski May 26 '18 at 18:18
  • `getUserTags = (id) => User.findById(id).exec().catch(next);` – Jonathan Lonowski May 26 '18 at 18:25

3 Answers3

0

You maybe need to return User.findById? Like so:

getUserTags = (id) => {
return User.findById(id)
.exec( (error, user) => {
  if (error) {
    return next(error);
  } else {       
    return user;
  }
})
}
DenLilleMand
  • 3,732
  • 5
  • 25
  • 34
  • It does not work, still returns undefined. – Ismat Valiev May 26 '18 at 18:12
  • problem is that User.findById is async so when getUserTags gets called it calls this function but returns immediately it self. So you have to figure out a way to make getUserTags depend on a promise. – DenLilleMand May 30 '18 at 11:15
0

findById is an asynchronous method.

If your node version greater then 8

getUserTags = id => User.findById(id).exec();

userTagToBookTagValues = async (id) => {
  try {
    const user = await getUserTags(id);
    user.tags.forEach(tag => {
      console.log(tag)
    });
  } catch (err) {
    next(err);
  }
}

Or you can use then method after calling getUserTags function.

For more information about of asnc methods:

Medium

Murat Ersin
  • 428
  • 6
  • 12
0

As I understand .exec() do not return anything, so using .then gives error. However if rewritten like this, it works perfectly:

getUserTags = (id) => {
  return User.findById(id)
}

userTagToBookTagValues =  (id) => {
const user =  getUserTags(id).then((user) => {
  user.tags.forEach(tag => {
    console.log(tag)
  });
  }) ;
}
Ismat Valiev
  • 135
  • 7
  • Note: `.exec()` will return a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) as long as you **don't** pass it a `callback`. Internally, the library manages this via [`utils.promiseOrCallback(...);`](https://github.com/Automattic/mongoose/blob/5.1.2/lib/query.js#L3103-L3117). – Jonathan Lonowski May 26 '18 at 19:03