Reputation:
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);
Upvotes: 0
Views: 83
Reputation: 2474
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');
})
Upvotes: 2
Reputation: 16029
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.
Upvotes: 4
Reputation: 741
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');
}
}
Upvotes: 1