Hi i have want to connect to mongo db to check if user is already registered or not if not i want to save user phone_number and make a code for his login and if he is already registered i want to just send the code for login
the problem is when i wrote the code it doesn't check the (if) statement and continues to end and send empty error
userModel.findOne({phone_number: req.body.phone_number}).then(function (err, res) {
console.log('if start');
if (err) {
res.send(err)
} else {
if (res.length){
codeModel.create({
phone_number: req.body.phone_number,
code_Number: Math.floor((Math.random() * 5000) + 1000)
}).then(function (created) {
console.log('response then');
res.status(200).send(created);
})
}
else {
console.log("blah blah blah");
userModel.create(req.body).then(function (jobs) {
res.status(200).send(jobs)
})
}
}
i found it myself the error is do to .then placement it should be after function
userModel.findOne({phone_number:req.body.phone_number},function (err, user) {
if (err){
res.status(400).send(err)
}
}).then(function (result) {
console.log(result + " data ");
console.log('user');
if (result == null || result == ''){
//user peida nashod
console.log('peida nashod');
userModel.create(req.body).then(function (resp) {
console.log(resp + " resp ");
}).catch(next);
codeModel.create(req.body).then(function (code) {
console.log(code);
res.status(200).send({
message:"afarin",
code: code
})
}).catch(next)
}
else {
codeModel.create(req.body).then(function (code) {
console.log(code);
res.status(200).send({
message:"afarin",
code: code
})
}).catch(next)
}
}).catch(next)
Related
I am trying to call a function inside my post API. I have multiple queries and want to wait for the function to complete in order to execute the next queries. I am having an issue here. The function isn't completing the execution and the rest of the API gets executed as expected. How can I wait for the function to complete its execution? I have searched but couldn't find something convenient and related to my code.
Here's the code:
Node.js
function verifyEmail(mailToUpper)
{
var emailResult;
db2.open(mydbConnection, (err, conn) => {
if(!err)
{
console.log("Connected Successfully");
}
else
{
console.log("Error occurred while connecting to the database " + err.message);
}
conn.query(checkEmailQuery, [mailToUpper], (err, results) => {
if(!err)
{
if(results.length > 0)
{
// res.write("Email already exists");
emailResult = 0;
}
else
{
emailResult = 1;
}
}
conn.close((err) => {
if(!err)
{
console.log("Connection closed with the database");
}
else
{
console.log("Error occurred while trying to close the connection with the database " +
err.message);
}
})
})
})
return emailResult;
}
router.post('/api/postData', (req, res) => {
//some stuff
var waitingForResult;
setTimeout(() => {
waitingForResult = verifyEmail(mailToUpper);
}, 2000)
console.log(waitingForResult); //throwing an error of undefined
if(waitingForResult === 1) //not executing this
{
//my other queries
}
else //always executes this
{
res.send("Email already exists");
}
});
function verifyEmail(mailToUpper) {
return new Promise((resolve, reject) => {
db2.open(mydbConnection, (err, conn) => {
if (!err) {
console.log("Connected Successfully");
} else {
console.log("Error occurred while connecting to the database " + err.message);
}
conn.query(checkEmailQuery, [mailToUpper], (err, results) => {
if (!err) {
if (results.length > 0) {
// res.write("Email already exists");
resolve(0);
} else {
resolve(1);
}
}
conn.close((err) => {
if (!err) {
console.log("Connection closed with the database");
} else {
console.log("Error occurred while trying to close the connection with the database " +
err.message);
}
})
})
})
})
}
router.post('/api/postData', async (req, res) => {
const waitingForResult = await verifyEmail( mailToUpper );
if( waitingForResult === 1 ){
//my other queries
} else {
res.send("Email already exists");
}
});
Below is controller.js script. I am facing hard time to go inside if loop "if(changeUserToSellerFlag == 1)" because this if statement is executed much earlier than this if statement "if (results.Name == "Customer")". I am not sure why the order of execution is not done line by line.
const { updateUserSellerStatus } = require("./seller.model.js");
const { genSaltSync, hashSync } = require("bcrypt");
const userid = require("../auth/token_validation.js");
const {
updateUserRoleAfterSellerApproval,
getRoleName,
} = require("../users/user.service.js");
module.exports = {
sellerVerify: (req, res) => {
var sellerStatusName;
var changeUserToSellerFlag = 0; // this flag determines if user to seller update is needed or not
approvedByName = req.fullName; //get full name from token_validation.js
approvedByEmail = req.email; //get email from token_validation.js
console.log("Request body is below");
console.log(req.body); // contains body sent by postman
updateUserSellerStatus(
req.body,
approvedByName,
approvedByEmail,
(err, results) => {
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
if (!results) {
console.log(results);
return res.json({
success: 0,
message: err,
});
}
if (req.body.sellerStatus == 3) {
sellerStatusName = "Rejected";
} else if (req.body.sellerStatus == 2) {
sellerStatusName = "Completed";
} else if (req.body.sellerStatus == 1) {
sellerStatusName = "Pending";
}
//verify if user is a seller or not
if (req.userId) {
getRoleName(req.userId, (err, results) => {
console.log("check rolename gettign below");
console.log(results);
if (results.Name == "Customer") {
console.log("User is Customer");
changeUserToSellerFlag = 1;
console.log("flag is :" + changeUserToSellerFlag);
} else if (results.Name == "Seller") {
console.log("User is Seller");
changeUserToSellerFlag = 0;
}
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
});
}
console.log("see flag changed here ", changeUserToSellerFlag);
if (changeUserToSellerFlag == 1) {
console.log("i am here");
//update userrole to seller only if user is not a seller earlier
updateUserRoleAfterSellerApproval(
req.userId,
req.roleId,
(err, results) => {
console.log("result details are bwlo");
console.log(results);
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
if (!results) {
console.log(results);
return res.json({
success: 0,
message: err,
});
}
console.log("Update into UserRole Completed successfully");
},
);
} else {
console.log(
"User is already a seller and dont need to update userrole table",
);
}
console.log(sellerStatusName);
return res.status(200).json({
success: 1,
status: sellerStatusName,
});
},
);
},
};
Below is console output
Request body is below
{ sellerId: 122, sellerStatus: 2 }
see flag changed here 0
User is already a seller and dont need to update userrole table
Completed
check rolename gettign below
TextRow { Name: 'Customer', RoleId: 2 }
User is Customer
flag is :1
where "User is already a seller and dont need to update userrole table" is executed first before "flag is :1"
to me it looks as if you're treating asynchronous code as if it was synchronous. At the top of the function you are calling parts of the code that are asynchronous, like for example every database query is generally async call.
getRoleName(req.userId, (err, results) //i assume this is an async call
process will not wait for the above code to finish before proceeding forward with its execution because it is written synchronously. So next instructions that it will execute are:
console.log('see flag changed here ', changeUserToSellerFlag);//0
if(changeUserToSellerFlag == 1)//0 --> false
}else{console.log("User is already a seller and dont need to update userrole table");}//so these 3 orders are executed immediately.
after which the async call from (i assume)
getRoleName(req.userId, (err, results)
will have finished and the proper callback will be called.
as a potential solution:
I would either wait for any database call to finish before proceeding. You can use async - await call, other solutions are also usage of Promises and of course making a callback hell.
If we use callback because you are already using them it would look something like this:
updateUserSellerStatus(
req.body,
approvedByName,
approvedByEmail,
(err, results) => {
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
if (!results) {
console.log(results);
return res.json({
success: 0,
message: err,
});
}
if (req.body.sellerStatus == 3) {
sellerStatusName = "Rejected";
} else if (req.body.sellerStatus == 2) {
sellerStatusName = "Completed";
} else if (req.body.sellerStatus == 1) {
sellerStatusName = "Pending";
}
//verify if user is a seller or not
if (req.userId) {
getRoleName(req.userId, (err, results) => {
console.log('check rolename gettign below');
console.log(results);
if (results.Name == "Customer") {
console.log("User is Customer");
changeUserToSellerFlag = 1;
console.log("flag is :" + changeUserToSellerFlag);
} else if (results.Name == "Seller") {
console.log("User is Seller");
changeUserToSellerFlag = 0;
}
console.log('see flag changed here ', changeUserToSellerFlag);
if (changeUserToSellerFlag == 1) {
console.log("i am here");
//update userrole to seller only if user is not a seller earlier
updateUserRoleAfterSellerApproval(
req.userId,
req.roleId,
(err, results) => {
console.log("result details are bwlo");
console.log(results);
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
if (!results) {
console.log(results);
return res.json({
success: 0,
message: err,
});
}
console.log("Update into UserRole Completed successfully");
}
);
} else {
console.log("User is already a seller and dont need to update userrole table");
}
console.log(sellerStatusName);
return res.status(200).json({
success: 1,
status: sellerStatusName,
});
}
if (err) {
console.log(err);
return res.status(500).json({
success: 0,
message: err,
});
}
});
}
);
},
};
I just moved the code which was below the
console.log('see flag changed here ', changeUserToSellerFlag);
inside the first callback method.
I'd recommend refactoring the callback-hell asynchronicity to promises.
Happily, util.promisify in Node's util library makes it super easy to do that for functions that are callback-async.
You end up with something like this:
const { promisify } = require("util");
const { updateUserSellerStatus } = require("./seller.model.js");
const userid = require("../auth/token_validation.js");
const {
updateUserRoleAfterSellerApproval,
getRoleName,
} = require("../users/user.service.js");
const updateUserSellerStatusP = promisify(updateUserSellerStatus);
const getRoleNameP = promisify(getRoleName);
const updateUserRoleAfterSellerApprovalP = promisify(
updateUserRoleAfterSellerApproval,
);
async function sellerVerify(req) {
var sellerStatusName;
var changeUserToSellerFlag = 0; // this flag determines if user to seller update is needed or not
switch (req.body.sellerStatus) {
case 3:
sellerStatusName = "Rejected";
break;
case 2:
sellerStatusName = "Completed";
break;
case 1:
sellerStatusName = "Pending";
break;
}
const results = await updateUserSellerStatusP(
req.body,
req.fullName,
req.email,
);
if (!results) throw new Error("No results from UUSS");
//verify if user is a seller or not
if (req.userId) {
const roleName = await getRoleNameP(req.userId);
if (roleName.Name === "Customer") {
changeUserToSellerFlag = 1;
} else if (roleName.Name === "Seller") {
changeUserToSellerFlag = 0;
}
}
if (changeUserToSellerFlag) {
console.log("i am here");
//update userrole to seller only if user is not a seller earlier
const results = await updateUserRoleAfterSellerApprovalP(
req.userId,
req.roleId,
);
console.log(results);
if (!results) throw new Error("UURASP results missing");
console.log("Update into UserRole Completed successfully");
} else {
console.log(
"User is already a seller and dont need to update userrole table",
);
}
console.log(sellerStatusName);
return {
success: 1,
status: sellerStatusName,
};
}
module.exports = {
sellerVerify: async (req, res) => {
try {
const result = await sellerVerify(req);
return res.json(result);
} catch (err) {
console.error(err);
return res.status(500).json({
success: 0,
message: err,
});
}
},
};
I send data from my input fields to my api:
$.ajax({
url: '/api/login',
type: 'GET',
dataType: 'json',
ContentType: 'application/json',
data: {formData},
success: (data) => {
console.log('SUCCESS')
console.log(data)
this.setState({
isInProcess: false
})
},
error: (jqXHR) => {
console.log(jqXHR)
console.log('ERROR')
this.setState({isInProcess: false})
}
})
on my server-side I have a function to see if I have required user in db:
async function findUser(data) {
try {
const user = await User.findOne({email: data.email,
password: data.password})
console.log('User was found')
return { user }
} catch (err) {
console.log('error', err)
throw err
}
}
which will be executed here:
app.get('/api/login', async (req, res) => {
const data = req.query
try {
const foundUserData = await findUser(data.formData)
return res.json(foundUserData)
} catch (err) {
return res.status(400).json(err)
}
})
It works fine, but if a user wasn't found in db i sends success anyway. Why?
await findUser(data.formData) won't throw error, return either null or user object. You may check something following
app.get('/api/login', async (req, res) => {
const data = req.query
try {
const foundUserData = await findUser(data.formData)
if(foundUserData && foundUserData.user) {
return res.json(foundUserData)
} else {
return res.status(400).json({message: 'User not found'});
}
} catch (err) {
return res.status(500).json(err)
}
})
It sends success because none of your queries error'ed, just because it didn't find anything does not mean that the query failed because it obviously succeeded in finding out if what ever you're looking for exists or not.
To send an error in case of not found you need to check if response is empty in which case you want to send error
When no user is find you get a null value. You may try to put more logic on your success parameter with that for example:
success: function (data) {
if(!!data && data != null) {
alert('Success');
} else {
alert('No data');
}
}
I have mocha tests. I will simplify as possible as I can.
I wonder how should I handle the errors in mocha tests. For example, if there is an error in getName, what should I do? How can I throw an error? Or should I use done(error) as;
it('trial', function(done) {
getName(function (name, err) {
if(err){
done(err); //what should I do here?
}else{
console.log(name);
}
});
});
If doneis called with a argument other than undefined, the test will fail and be reported as such. Other test will still be executed.
It allow you to test for success, but also for error:
it('succeed', (done) => {
myFunc('success', (err, res) => {
if(err) {
done(err);
} else if(res !== 'expected') {
done('Wrong result ' + res);
} else {
done();
}
});
});
it('fail with error 404', (done) => {
myFunc('fail', (err, res) => {
if(err) {
if(err === 404) {
done();
} else {
done('Error was expected to be 404, got ' + err);
}
} else {
done('Was expected to fail, got result ' + res + ' and no error');
}
});
});
it('succeed', (done) => {
try {
var res = myFuncSync('succeed');
} catch(err) {
done(err);
}
done();
});
it('fail with error 404', (done) => {
try {
var res = myFuncSync('succeed');
} catch(err) {
if(err === 404) {
done();
} else {
done('Error was expected to be 404, got ' + err);
}
}
done('Was expected to fail, got result ' + res + ' and no error');
});
I anticipate a callback hell is beginning to form in my code so I decided to start using promises. But I can't wrap my head around implementing it. For example I have a function:
DB.prototype = {
findUser: function (username) {
this._pool.getConnection(function (err, connection) {
if (err) { return callback(true, false); }
connection.query('SELECT password_hash, password_salt FROM users WHERE email = ? AND admin = 1', username,
function (err, rows) {
connection.release();
if (rows.length === 1) { callback(false, rows[0]); }
else { callback(false, false); }
});
connection.on('error', function () { callback(true, false); });
});
}
};
How would I adapt this to using promises instead of callbacks? And how would I use this adapted db.findUser() ?
EDIT:
I got something working. It looks like this:
DB.prototype = {
getConnection: function() {
return this._pool.getConnectionAsync();
}
}
And the usage:
Promise.using(db.getConnection(), function(connection) {
return connection.queryAsync("SELECT password_hash, password_salt FROM users WHERE email = ? AND admin = 1", "exampleUser")
.then(function(rows) {
connection.release();
console.log("is there a row?", rows.length === 1, rows);
// do something with results
});
}).catch(function(err) {
// This is only run if an error is thrown
console.log("error is", err);
});
Is this a good implementation or could something be improved?