In Nodejs, how wait process until response back from function - node.js

I am new to Nodejs. Process is not waiting until response back from function. Because of asynchronous calling of Nodejs. how to make synchronous. Please help me.
Here is my code
module.exports.signup = function(req, res){
console.log('signup');
User.findOne({'emails.email' : req.body.email}, function(err, doc) {
if (doc === null) {
var vr_token= genRandomString(16);
var ex_date = Date.now();
var user = new User();
user.emails.push({
email : req.body.email,
email_verification_token : vr_token,
verify_key_expire : ex_date });
user.save(function(err2,user1) {
if (!err2) {
var result = send_email.sync(vr_token);//process not waiting
if(result) {
res.json ({
status: 200,
message:"mail sent successfully",
data:user1
})
}
}
});
}
})
}
here is my function
function send_email(vr_token){
var mailOpts = {
from: process.env.Mail_From_Addr,
to: 'xxxxxxxxxxxxx',
subject: 'Verify Your New Account Email',
html:'<p>Hello,</p>code : '+vr_token
};
mailgun.messages().send(mailOpts, function (err, response){
if (!err){
return true;
}else{
return false;
}
})
}

Add a callback to it:
function send_email(vr_token, callback){
var mailOpts = {
from: process.env.Mail_From_Addr,
to: 'xxxxxxxxxxxxx',
subject: 'Verify Your New Account Email',
html:'<p>Hello,</p>code : '+vr_token
};
mailgun.messages().send(mailOpts, function (err, response){
callback(null, !err);
})
}
The Code:
module.exports.signup = function(req, res){
console.log('signup');
User.findOne({'emails.email' : req.body.email}, function(err, doc) {
if (doc === null) {
var vr_token= genRandomString(16);
var ex_date = Date.now();
var user = new User();
user.emails.push({
email : req.body.email,
email_verification_token : vr_token,
verify_key_expire : ex_date });
user.save(function(err2,user1) {
if (!err2) {
send_email.sync(vr_token, function(err, result){
if(result) {
res.json ({
status: 200,
message:"mail sent successfully",
data:user1
})
}
});
}
});
}
})
}

Related

TypeError: Cannot read property 'then' of undefined in node js

this is the .sms file . I'm trying to call an resendOTP api but im geeting an error that .then is undefined
var aws = require('aws-sdk')
aws.config.update({
region: '********',
accessKeyId: "********",
secretAccessKey:"*********"
});
var sns = new aws.SNS();
sns.setSMSAttributes({
attributes: { DefaultSMSType: "Transactional" }
},
function (error) {
if (error) {
console.log(error);
}
});
function sendSms(phoneNumber, body) {
// console.log(`Sending SMS. Phone: ${phoneNumber}, body: ${body}`);
var params = {
Message: body,
MessageStructure: 'string',
PhoneNumber: phoneNumber
};
sns.publish(params, function (err, data) {
if (err) {
console.log(err, err.stack); // an error occurred
}
else {
// console.log(data); // successful response
}
});
}
module.exports = sendSms
.then is showing undefined.
exports.resendOTP = async( req, res) => {
const { id } = req.body;
const user = await User.findOne({ _id : id })
if (!user) {
res.status(200).send({
message: "User was not found"
});
}
else {
var OTP = Math.floor(1000 + Math.random() * 9000);
var encryptOTP = encrypt(OTP.toString());
var body = 'Hi, '+OTP+' is your One Time Password.';
sendSms(user.countryCode+user.phoneNumber, body).then(message => {
if (message) {
res.status(200).send({
message: "Updated Sucessfully"
});
}
})
}
}

Async handling issue in nodejs

I am new in nodejs. I am creating a basic API to get record by id. Everything is working fine. It is returning user data from database. But when i use password variable from response in same function it give me empty value whereas i am getting value in response. I think this is async issue but i dont know how to fix it.
This is API code
var express = require('express');
var db = require('../db/database');
var bcrypt = require('bcrypt');
const router = express.Router();
router.get("/:userId", (req, res, next) => {
let uid = req.params.userId;
db.query(`SELECT * FROM users WHERE u_id = ${uid}`, (err, data)=> {
if(!err) {
if(data && data.length > 0) {
var message = '';
if(data.u_password){
//var pass = data.u_password;
if(bcrypt.compare('123456', data.u_password)) {
// Passwords match
message = 'Passwords match';
} else {
// Passwords don't match
message = 'Passwords dont match';
}
}
res.status(200).json({
message:message,
});
} else {
res.status(200).json({
message:"User Not found."
});
}
}
});
});
database.js
var mysql = require('mysql');
const pool = mysql.createPool({
connectionLimit : 10,
host: 'localhost',
user: 'root',
password: '',
database: 'lost_and_found',
debug : false
});
function executeQuery(sql, callback) {
pool.getConnection((err,connection) => {
if(err) {
return callback(err, null);
} else {
if(connection) {
connection.query(sql, function (error, results, fields) {
connection.release();
if (error) {
return callback(error, null);
}
return callback(null, results);
});
}
}
});
}
function query(sql, callback) {
executeQuery(sql,function(err, data) {
if(err) {
return callback(err);
}
callback(null, data);
});
}
module.exports = {
query: query
}
Response
{"message":""}
Please change the bcrypt.compare code to following code. It is a callback function:
bcrypt.compare('123456', data.u_password, function(err, result) {
if (err) {
// Passwords don't match
message = 'Passwords dont match';
} else {
// Passwords match
message = 'Passwords match';
}
res.status(200).json({
message:message,
});
})
EDIT 1: Please update the method to following logic:
db.query(`SELECT * FROM users WHERE u_id = ${uid}`, (err, data) => {
if (err) {
throw err;
}
if (data && data.length > 0) {
var message = '';
if (data.u_password) {
bcrypt.compare('123456', data.u_password, function (err, result) {
if (err) {
// Passwords don't match
message = 'Passwords dont match';
} else {
// Passwords match
message = 'Passwords match';
}
res.status(200).json({
message: message,
});
})
}
res.status(200).json({
message: "User Not found."
});
}
res.status(200).json({
message: "User Not found."
});
});

How to call a funtion in another function in Node.js

I want to call other function and how to get the results of that function,
function1,
exports.getprofiledatalistbyid = function (req, res) {
var params = req.params;
var profile= db.collection('profile');
var requests= db.collection('requests');
profile.find().toArray((err, result) => {
if (err){ return console.log(err)
}
if(result){
// console.log(result)
for(var i in result){
var id = result[i]._id;
var id = id.toString();
exports.getdetails(id)
}
}
else{
response = {status:'fail',data:[] };
}
// res.send(response);
});
};
function2,
exports.getdetails = function (req,res) {
// var profile= db.collection('profile');
var requests= db.collection('requests');
var params = req.params;
var id = params.id;
requests.find( { $or:[ {'sent_id':id}, {'recieved_id':id}]}).toArray((err, result) => {
if (err){ return console.log(err)
}
if(result){console.log(result)
return result;
}
else{
response = {status:'fail',data:[] };
}
});
};
routes,
var profile = require('../controller/user');
router.get('/getprofiledatalistbyid/:id?', cors(), profile.getprofiledatalistbyid);
So here I want to use the results of function 2 in function 1.
Can someone helps me?
Thanks.
Use module.exports and call your functions by this
module.exports = {
getprofiledatalistbyid: function(req, res) {
var params = req.params;
var profile = db.collection('profile');
var requests = db.collection('requests');
profile.find().toArray((err, result) => {
if (err) {
return console.log(err)
}
if (result) {
// console.log(result)
for (var i in result) {
var id = result[i]._id;
var id = id.toString();
this.getdetails(req,res,function(err,result){
if(!err)
console.log(result);
});
}
} else {
response = {
status: 'fail',
data: []
};
}
// res.send(response);
});
},
getdetails: function(req, res,callback) {
// var profile= db.collection('profile');
var requests = db.collection('requests');
var params = req.params;
var id = params.id;
requests.find({
$or: [{
'sent_id': id
}, {
'recieved_id': id
}]
}).toArray((err, result) => {
if (err) {
return callback(err)
}
if (result) {
console.log(result)
return callback(null,result);
} else {
callback(null, {
status: 'fail',
data: []
});
}
});
}
};

REST api redundancy

So i am creating a RESTFul api for my application using Node.js
However it is starting to feel abit redundant and therefore i am wondering if i am doing it correctly.
So when ever i have a new model i do the following:
First i create a file equal to the table name in the database (lets take a table called team as an example):
// IMPORT ROUTES
// =============================================================================
module.exports = function (express, sequelize, router) {
router.route('/team');
var DataTypes = require("sequelize");
var crypto = require('crypto');
// on routes that end in /Teams
// ----------------------------------------------------
router.route('/api/team')
// create a Team (accessed at POST http://localhost:8080/api/Teams)
.post(function (req, res) {
var name = req.body.name; //bodyParser does the magic
var academy_id = req.body.academy_id;
var team = Team.build({name: name, academy_id: academy_id});
team.add(function (success) {
res.json({message: 'Team created!'});
},
function (err) {
res.status(err).send(err);
});
})
// get all the Teams (accessed at GET http://localhost:8080/api/Teams)
.get(function (req, res) {
var team = Team.build();
team.retrieveAll(function (Teams) {
if (Teams) {
res.json(Teams);
} else {
res.status(401).send("Team not found");
}
}, function (error) {
res.status("Team not found").send('Team not found');
});
});
var Team = sequelize.define('team', {
id: DataTypes.INTEGER,
name: DataTypes.STRING,
academy_id: DataTypes.INTEGER
}, {
freezeTableName: true,
instanceMethods: {
retrieveAll: function (onSuccess, onError) {
Team.findAll({}, {raw: true})
.ok(onSuccess).error(onError);
},
retrieveById: function (Team_id, onSuccess, onError) {
Team.find({where: {id: Team_id}}, {raw: true})
.success(onSuccess).error(onError);
},
add: function (onSuccess, onError) {
var Teamname = this.name;
var password = this.password;
var shasum = crypto.createHash('sha1');
shasum.update(password);
password = shasum.digest('hex');
Team.build({name: Teamname, name: password})
.save().ok(onSuccess).error(onError);
},
updateById: function (Team_id, onSuccess, onError) {
var id = Team_id;
var Teamname = this.Teamname;
var password = this.password;
var shasum = crypto.createHash('sha1');
shasum.update(password);
password = shasum.digest('hex');
Team.update({Teamname: Teamname, password: password}, {where: {id: id}})
.success(onSuccess).error(onError);
},
removeById: function (Team_id, onSuccess, onError) {
Team.destroy({where: {id: Team_id}}).success(onSuccess).error(onError);
},
retrieveByAcademyId: function(academy_id, onSuccess, onError)
{
Team.findAll({where: {academy_id: academy_id}}, {raw: true})
.ok(onSuccess).error(onError);
}
}
}
),
academy = sequelize.define('academy', {
id: DataTypes.INTEGER,
name: DataTypes.STRING,
organization_id: DataTypes.INTEGER,
status_id: DataTypes.INTEGER
});
Team.belongsTo(academy,{foreignKey: 'academy_id'});
// on routes that end in /Teams/:Team_id
// ----------------------------------------------------
router.route('/api/team/:team_id')
// update a Team (accessed at PUT http://localhost:8080/api/Teams/:Team_id)
.put(function (req, res) {
var team = Team.build();
team.name = req.body.name;
team.academy_id = req.body.academy_id;
team.updateById(req.params.id, function (success) {
console.log(success);
if (success) {
res.json({message: 'Team updated!'});
} else {
res.send(401, "Team not found");
}
}, function (error) {
res.send("Team not found");
});
})
// get a Team by id(accessed at GET http://localhost:8080/api/Teams/:Team_id)
.get(function (req, res) {
var team = Team.build();
team.retrieveById(req.params.team_id, function (teams) {
if (teams) {
res.json(teams);
} else {
res.status(401).send("Team not found");
}
}, function (error) {
res.send("Team not found");
});
})
// delete a Team by id (accessed at DELETE http://localhost:8080/api/Teams/:Team_id)
.delete(function (req, res) {
var team = Team.build();
team.removeById(req.params.id, function (teams) {
if (teams) {
res.json({message: 'Team removed!'});
} else {
res.status(401).send("Team not found");
}
}, function (error) {
res.send("Team not found");
});
});
router.route('/api/academyTeam/:academy_id')
.get(function (req, res) {
var team = Team.build();
team.retrieveByAcademyId(req.params.academy_id, function (teams) {
if (teams) {
res.json(teams);
} else {
res.status(401).send("Team not found");
}
}, function (error) {
res.send("Team not found");
});
});
return router;
};
Then afterwards i add the following line to my server.js:
app.use(team_model);
then i repeat the action for the next table.
Am i doing it right or is there a way to optimize things?

How to return a value from a mysql SELECT query in node.js

I'm still very new to Node.js, and i'm trying to understand how callbacks work.
So, here is my problem :
I should've put more code :
POST :
app.post('/register', function(req, res) {
//get data from the request
var data = {
username: req.body.username,
email: req.body.email,
password: req.body.password
};
function fetchID(callback) {
connection.query('SELECT id_user FROM USERS WHERE username = ?', data.username, function(err, rows) {
if (err) {
callback(err, null);
} else
callback(null, rows[0].id_user);
});
}
var user_id;
fetchID(function(err, content) {
if (err) {
console.log(err);
return next("Mysql error, check your query");
} else {
user_id = content;
console.log(user_id); //undefined
}
});
console.log(user_id); //undefined
var payload = {
iss: req.hostname,
sub: user_id
}
console.log(payload.sub); //correct id
})
GET :
app.get('/todos', function(req, res) {
if (!req.headers.authorization) {
return res.status(401).send({
message: 'You are not authorized !'
});
}
var token = req.headers.authorization.split(' ')[1];
var payload = jwt.decode(token, "shhh..");
//additional level of security
console.log('sub id is : ' + payload.sub); //undefined
if (!payload.sub) {
return res.status(401).send({
message: 'Authentication failed !'
});
}
})
I commented each console.log to be more clear. I need to get the correct id when i check for if (!payload.sub) in app.get()
Your two functions should be something like -
function fetchID(data, callback) {
connection.query('SELECT id_user FROM USERS WHERE username = ?', data.username, function(err, rows) {
if (err) {
callback(err, null);
} else
callback(null, rows[0].id_user);
});
}
and then
var user_id;
fetchID(data, function(err, content) {
if (err) {
console.log(err);
// Do something with your error...
} else {
user_id = content;
}
});
Here in the callback function, the returned variable content will hold the value for user_id.
EDIT
I have not solved the exact problem as you had described above.
But in following example, I have shown that, the callback mechanism is working -
First (Table creation and insert some dummy data)-
use test;
create table users (id int(11) primary key,username varchar(100));
insert into users values(1, "John");
insert into users values(2, "Sham");
Now I have made your post method as get and tested in browser.
Following is the full class tested in my localhost -
var application_root = __dirname,
express = require("express"),
mysql = require('mysql');
var app = express();
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'admin',
database: "test"
});
app.get('/getuser', function(req, res) {
//get data from the request
var data = {
username: req.query.username
};
function fetchID(data, callback) {
connection.query('SELECT id FROM users WHERE username = ?',
data.username, function(err, rows) {
if (err) {
callback(err, null);
} else
callback(null, rows[0].id);
});
}
var user_id;
fetchID(data, function(err, content) {
if (err) {
console.log(err);
res.send(err);
// Do something with your error...
} else {
user_id = content;
console.log(user_id);
res.send("user id is -" + user_id);
}
});
})
app.listen(1212);
Now these requests will produce this output -
http://127.0.0.1:1212/getuser?username=john => user id is -1 and
http://127.0.0.1:1212/getuser?username=sham => user id is -2
Hope this code example will help you to understand the callback in node.js.
Thanks

Resources