0

Am trying to create a method that i can call from all parts of my express app, i simply pass a value to this method and it searches through mongodb using moongose to see if user exists, then it returns a Boolean as result.

function findUserExists(name){

 User.findOne({ "name": name }, function(err, user) {

 if (user){ 
    console.log("user exits");
    return true;
 }
 else{ 
        console.log("user not exits");
    return false; }
});

Now when i call it in another method like this, it doesn't return the Boolean value in time.

if (findUserExists("username")){

// redirect to dashboard
console.log("user exits");
    res.redirect('/dashboard');
}
else {
 // redirect to sign up page
console.log("user must sign up");
    res.redirect('/signup');
}

So in this case the other functions run before getting the Boolean value from the findUserExists(), my question is how can i make this function return a value before other functions run, in a way that i can call it in an IF condition or even a var like this

var exists = findUserExists(name);
  • 1
    Can you nest "other function" in a if statement? or call them from your if (findUserExists("username")){ //the function to call } – Sulot May 22 '16 at 10:00
  • 1
    @Sulot it's only a routing statement to know if user exists then redirect to dashboard page, if not redirect to sign up page, i updated my question –  May 22 '16 at 10:16
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – JJJ May 22 '16 at 11:00

3 Answers3

4

You are trying to force synchronous code on asynchronous function. Short answer is: you shouldn't do this

Convert your function to callback

function findUserExists(name, callback) {
    User.findOne({ "name": name }, function (err, user) {
        callback(user);
    });
}

and then use as this:

findUserExists("username", function (exists) {
    if (exists) {
        console.log("user exits");
        res.redirect('/dashboard');
    } else {
        console.log("user must sign up");
        res.redirect('/signup');
    }
});

You can use promises to code look more synchronous if you use node 4 and above.

Everettss
  • 15,475
  • 9
  • 72
  • 98
2

In your logic there is a problem, you are not handling errors that might occur in the query itself like DB server down. Avoid using callbacks as much as possible and switch to promises, async await, etc..

Using Promises:

If no call back is passed to Mongoose, then it will return a Promise. If query is successfull it will resolve with document. In this case if user does not exists, then it will be resolved with a null (link), if user exists then it will be resolved with that document. In case if query fails, for example DB server unavailable etc, then the promise will be rejected with an err object.

DB call

  function findUserExists(name){
    return User.findOne({ "name": name })
    .then(function(doc){//This function will be executed if DB query was successful.
      //You can write additional logic if any to handle the returned doc here
      return doc;
    }, function(err){// This function will be executed if something goes wrong with db server or query.
      //You can write logic for error handling in DB connection like logging DB failure.
      return err;
    })
  }

Validation:

findUserExists(name)
.then(function(user){//Resolved callback: This function is executed if previous promise was resolved
  if(!user){ //If user does not exist null will be returned
    console.log('User must sign up');
    return res.redirect('/signup');
  }
  console.log('User Exists');
  return res.redirect('/dashboard');
},function(err){ //This function is executed if previous promise is rejected
  console.log('Some error occurred in DB query');
})
Nidhin David
  • 2,426
  • 3
  • 31
  • 45
  • 1
    Nice deeply explanation. You cover promises and error handling which are important in real application. Ceddy's question didn't mentioned error handling - sometimes it's better to extract only problem from your application and not trying to cover all possible topics. – Everettss May 22 '16 at 11:14
1

This is because your findUserExists function calls an asynchronous but you're trying to use it synchronously.

In order to achieve what you're looking to do, you need to provide your function with a callback function or return a promise. The easiest way, since you're already using callbacks in mongoose would be like this:

    function findUserExists(name , callback ){
     User.findOne({ "name": name }, function(err, user) {
      if( err ) callback( err );
      else if (user){
        console.log("user exits");
        callback( null, true );
      }
      else{
        console.log("user does not exist");
        callback( null, false );
      }
    });

    findUserExists( "username", function( err, user ){
      if( err ) console.log( err );
      else if( user ){
        console.log("user exits");
        res.redirect('/dashboard');
        // redirect to dashboard
      }
      else {
       // redirect to sign up page
        console.log("user must sign up");
        res.redirect('/signup');
      }
    }
leesio
  • 731
  • 3
  • 13