I'm currently trying to validate username and password in a function that calls another function from postgresql. My validation should return true in the validate function but it doesn't. The console.log above it works and the parameters I use when I actually use validate() should return true but isn't.
function validate(username, password){
//PG Connect
pool.connect((err, client, done)=>{
if(err){
return console.error('error fetching client from pool', err);
}
client.query('SELECT * FROM users', (err, result)=>{
if(err){
return console.error('error running query', err);
}
for(let i = 0; i < result.rows.length; i++){
if(result.rows[i].username.trim() == username && result.rows[i].password.trim() == password){
console.log("this works");
return true; //this doesn't return true when I call the function
}
console.log(result.rows[i].username.trim() + " " + result.rows[i].password.trim());
}
return false;
done();
});
});
}
The problem is that you're returning within the query's callback instead of the parent function. This means validate() is actually not returning anything.
An easy solution to this would be to make use of either a Promise or a callback on validate. Here is how you could implement the Promise method...
function validate(username, password) {
return new Promise((resolve, reject) =>
pool.connect((err, client, done) => {
if (err) {
return reject(err);
}
client.query('', (err, results) => {
done();
if (err) {
return reject(err);
}
// logic here
resolve(false); // failed validation
});
});
});
}
And you would use it like so...
validate('username', 'password')
.then(valid => console.log(valid))
.catch(err => console.error(err));
Where all your reject() calls are caught in the catch and all the resolve() calls are caught in then.
Related
the below is my controller function
exports.validateUsername = async (uName) => {
console.log("inside validate username");
await User.findOne({ username: "sab2" }).then(function (err, user) {
if (err) {
console.log("inside err");
console.log("error");
console.log(err);
return true;
} else {
console.log("inside user found");
console.log("user");
console.log(user);
return false;
}
});
};
I have record in my "user" collection with username ="sab2". But still , the promise function results in err, and goes inside if(err).
But when I do console.log(err) I get the actual user data "sab2" object.
I have a doubt if the function syntax is function(data,err).
Error object printed
Please suggest a solution.
The then() on a findOne does not return a error, I would rewrite like this:
User.findOne({ username: "sab2" }, function(err, user) {
if (err) {
console.log("inside err");
console.log("error");
console.log(err);
return true;
} else {
console.log("inside user found");
console.log("user");
console.log(user);
return false;
}
});
then do not return error. Do something like this to catch error
await User.findOne({ username: "sab2" }).then((user) => {
console.log(user)
}).catch(error=>console.log(error))
or use callback. See here
So I'm trying to create a function which checks if the user exists in the database, if they don't it then goes and imports them to the database. I'm trying to use the await feature so it waits for the function to be completed before moving on.
const doesUserExist = (id) => {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('db');
var users = dbo.collection('user');
return new Promise(function(resolve, reject) {
users.findOne({'id': id}, function (err, user) {
if (err) throw err;
console.log('User: ', user);
if (user === null) {
resolve(false);
} else {
resolve(true);
}
});
});
});
}
const userLogin = async (user) => { // User login function
var id = String(user.id);
// Check if the user exists
var doesExist = await doesUserExist(id);
console.log(doesExist);
if(doesExist===undefined){
console.log('ERROR: Exist is empty');
return;
}
if(doesExist===false){
console.log(`User with the id ${id} does not exist.`);
addUser(user);
} else {
console.log(`User with the id ${id} does exist.`);
}
}
You aren't returning a Promise from the doesUserExist function.
You are only returning a Promise in the callback of the MongoClient connect function.
You have to refactor your code this way :
const doesUserExist = (steamid) => {
return new Promise(function(resolve, reject) {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('treehouse');
var users = dbo.collection('users');
users.findOne({'steamid': steamid}, function (err, user) {
if (err) throw err;
console.log('User: ', user);
if (user === null) {
resolve(false);
} else {
resolve(true);
}
});
});
});
}
Now, the doesUserExist function is returning a Promise that is resolved in the findOne callback.
I am new to nodejs and I want to create helper function for finding user from collection. I want to excute that helper function before adding any new document into the database. Parallaly I want to use that helper function on multiple times in other places.
When I simply create one function and store result of that function, the control is passes from that place and doesn't wait for output as Nodejs basic Async functionality.
How can I customise my code to use helper function and wait for the result and then perform required operation
How to use nested callback ?
Nested callback isn't waiting for callback data and control goes to next line
Here is my code :
login: function (req, res) {
var user = helpers.checkIfDataExists(req.body.mobileNumber, function (user) {
if (user) {
console.log('user exists');
var email = helpers.checkIfDataExists(req.body.email, function (email) {
if (email) {
console.log('email exists');
} else {
console.log('email not exists');
}
});
} else {
console.log('user not exists')
}
});
}
I want that control waits till function is executed and then condition will get executed.
Here control goes by default in else part everytime.
Here is code of helper function :
checkIfDataExists: function (value, callback) {
User.find({mobileNumber: value})
.exec(function (err, result) {
if (err) {
console.log('Error occured');
callback(false);
} else {
console.log('result found');
callback(result);
}
});
},
Use callbacks. Pass a callback function to your helper function in which the results will be returned and then in your helper function write a call to that function when your computations are over.
checkIfDataExists: function (value, callback) {
User.find({mobileNumber: value})
.exec(function (err, result) {
if (err) {
console.log('Error occured');
callback(false);
} else if (!result) {
console.log('Not Found');
callback(false);
} else {
console.log('result found');
callback(result);
}
});
},
then use something like this in your main function.
signUp: function (req, res) {
var user = helpers.checkIfDataExists(req.body.mobileNumber, function(user){
// do something with results here
log(user);
if (!user) {
// add new user
} else {
res.send("User exists");
}
});
}
here is a link to article about callbacks
var usercoll = db.collection("users");
usercoll.findOne({email: config.registered.email}, function (err, user) {
console.log("after first find one");
if (err) {
console.log(err);
return
}
helper.registerUser("anewuser", function () {
browser.sleep(2000).then(function () {
usercoll.findOne({email: email}, function (err, newuser) {
console.log("after find one");
if (err) {
console.log(err);
return
}
;
console.log(newuser);
});
})
})
}
I can see "after first find one" in the console.
I can never see the output "after find one" in the console, and the tests just returns as if it worked, no error and success message.
But I am doing more stuff afterwards, and it seems it's never called. Why that? Is there some synchronization issue?
You need to create a promise and make it to wait till the script finds the new user,
var usercoll = db.collection("users");
var defer = protractor.promise.defer();
usercoll.findOne({email: config.registered.email}, function (err, user) {
console.log("after first find one");
if (err) {
console.log(err);
return
}
helper.registerUser("anewuser", function () {
browser.sleep(2000).then(function () {
usercoll.findOne({email: email}, function (err, newuser) {
console.log("after find one");
if (err) {
console.log(err);
return
}
;
console.log(newuser);
defer.fulfill(newuser);
});
})
})
}
defer.then(function(newUserDetails){
console.log(newUserDetails);
})
Hi lets say I have code like this:
router.get('/blablabla', function(req, res, next) {
model
.findOne({condition : req.body.condition})
.then(function(data) {
if(data) {
return res.send("data already exists");
}
else {
//DO CREATE THE NEW DATA
return modelInstance.save();
}
})
.then(function(data) {
if(data) res.send("new data successfully saved");
})
.catch(function(err) {
console.log(err);
});
});
In current condition if data already exists, there will be error
**[Error: Can't set headers after they are sent.]
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)**
Why this error raised? based on my knowledge after res.send() is being called then all the later code below it will not be executed right?
I am return data.save() because I want avoid nesting statement.
UPDATE ALTERNATIVE SOLUTION
router.get('/blablabla', function(req, res, next) {
model
.findOne({condition : req.body.condition})
.then(function(data) {
if(data) {
return new Promise(function(resolve, reject) {
return resolve();
});
}
else {
//DO CREATE THE NEW DATA
return modelInstance.save();
}
})
.then(function(data) {
if(data) res.send("new data successfully saved");
else res.send("data already exists");
})
.catch(function(err) {
console.log(err);
});
});
Your second .then() handler will still execute because the promise is not branched, it's chained so the chain keeps going and thus you will be doing two res.send() operations and that's what causes the error you see.
When you do:
return res.send("data already exists");
You are just returning a value from the .then() handler. Since that value is not a rejected promise, the promise stays resolved and the next .then() handler in the chain will execute.
You could do this:
router.get('/blablabla', function (req, res, next) {
model.findOne({condition: req.body.condition}).then(function (data) {
if (data) {
return res.send("data already exists");
} else {
//DO mMODIFY THE DATA AND THEN SAVE THE DATA
return data.save().then(function () {
res.send("new data successfully saved");
});
}
}).catch(function (err) {
console.log(err);
});
});
Or, you could do this (modification of your second try - assumes that data.save() returns a promise that resolves to a value):
router.get('/blablabla', function(req, res, next) {
model
.findOne({condition : req.body.condition})
.then(function(data) {
if (!data) {
//DO mMODIFY THE DATA AND THEN SAVE THE DATA
return data.save();
}
return data;
})
.then(function(data) {
if(data) res.send("new data successfully saved");
else res.send("data already exists");
})
.catch(function(err) {
console.log(err);
});
});