This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
api.js:
var db = require('./db.js');
console.log(searchAccessToken(name,queryDB));
searchAccessToken function:
function searchAccessToken(emailAddress,callback){
var sql = "SELECT accessToken FROM device WHERE email_address = '" + emailAddress + "'";
return callback(sql);
}
queryDB function:
function queryDB(sql){
var token = "";
db(function(err,conn){
conn.query(sql,function(err,results){
if(err){
conn.release();
return err;
}else if(results.length){
token = results[0].accessToken;
}
conn.release();
return token;
});
});
}
db.js
var mysql = require('mysql');
var pool = mysql.createPool({
//development
// host:'localhost',
// user:'root',
// password: '',
// database: 'merchantdev',
// insecureAuth : true
//staging
host:'',
user: '',
password: '',
database: ''
});
var getConnection = function(callback) {
pool.getConnection(function(err, connection) {
if(err) {
return callback(err);
}
callback(null, connection);
});
};
module.exports = getConnection;
I have read the other thread in SOF (How do I return the response from an asynchronous call?) but still unable to find out the mistake in my code. Please do not close this question as I have struggled for hours to find the solution but still couldn't. Console.log returns undefined when it is supposed to return a value.
Your callback function flow is not correct, you are calling asynchronous function that is conn.query
var db = require('./db.js');
// this function not required callback function
// as we are not doing anything asynchronous
function searchAccessToken(emailAddress){
var sql = "SELECT accessToken FROM device WHERE email_address = '" + emailAddress + "'";
return sql;
}
// this function required callback function
// as we are calling 2 asynchronous function
function queryDB(sql, callback){
var token = "";
db(function(err,conn){
conn.query(sql,function(err,results){
if(err){
conn.release();
return callback(err);
}else if(results.length){
token = results[0].accessToken;
}
conn.release();
return callback(null, token);
});
});
}
queryDB(searchAccessToken(name), function callback(err, token) {
if(err) return console.log(err)
console.log(token);
})
Checkout this snippet with callback error handling.
var db = require('./db.js');
function queryDB(sql, callback){
var token = "";
db(function(err,conn){
conn.query(sql,function(err,results){
if(err){
conn.release();
callback(err);
}else if(results && results.length > 0){
token = results[0].accessToken;
}
conn.release();
callback(null, token); //Returning Token as callback response
});
});
}
function searchAccessToken(emailAddress,callback){
var sql = "SELECT accessToken FROM device WHERE email_address = '" + emailAddress + "'";
queryDB(sql, (err, token) => {
if(err) {
callback(err);
} else {
callback(null, token);
}
})
}
searchAccessToken("xyz#gmail.com", (err, token) => {
if(err) {
console.log("Err :", err);
} else {
console.log("Token :", token);
}
});
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I have a function in typescrypt in file Service.ts:
export const doCallAuth = (username, password) => {
var auth = new Auth({
url: '...',
});
var status;
auth.authenticate(username, password, function (err, user) {
if (err) {
console.log(err);
status = 'no';
} else if (!user.uid) {
console.log("user not found Error");
status = 'no';
} else if (user.uid) {
console.log("success : user " + user.uid + " found ");
status = 'yes';
}
});
return status;
}
I call this method by :
var result = Service.doCallAuth('test', 'test');
And variable result is undefined
I don't know why result is undefined
Can anybody help me out ?
Thanks in advance. :)
You can use Promise or callback patterns
1. Promise
export const doCallAuth = (username, password) => {
return new Promise((resolve, reject) => {
var auth = new Auth({ url: "..." });
auth.authenticate(username, password, (err, user) => {
if (err) {
reject(err);
} else if (!user.uid) {
reject(new Error("user not found Error"));
} else if (user.uid) {
console.log("success : user " + user.uid + " found ");
resolve(user);
}
});
});
};
Service.doCallAuth("test", "test")
.then(user => {
console.log("success : user " + user.uid + " found ");
})
.catch(e => {
console.log(e);
});
2. Callback
export const doCallAuthCallBack = (username, password, callback) => {
var auth = new Auth({ url: "..." });
auth.authenticate(username, password, (err, user) => {
if (err) {
callback(err);
} else if (!user.uid) {
callback(new Error("user not found Error"));
} else if (user.uid) {
callback(null, user);
}
});
};
Service.doCallAuthCallBack("test", "test", (err, user) => {
if (err) {
console.log(err);
} else {
console.log("success : user " + user.uid + " found ");
}
});
Try this one.
export const doCallAuth = (username, password, callback) => {
var auth = new Auth({
url: '...',
});
var status;
auth.authenticate(username, password, callback);
}
var result;
Service.doCallAuth('test', 'test', function (err, user) {
if (err) {
console.log(err);
status = 'no';
} else if (!user.uid) {
console.log("user not found Error");
status = 'no';
} else if (user.uid) {
console.log("success : user " + user.uid + " found ");
status = 'yes';
}
result = status;
});
To get value from AJAX call need to Use async and await
export const doCallAuth = async function(username, password) => {
var auth = new Auth({
url: '...',
});
var status;
auth.authenticate(username, password, function (err, user) {
if (err) {
console.log(err);
status = 'no';
} else if (!user.uid) {
console.log("user not found Error");
status = 'no';
} else if (user.uid) {
console.log("success : user " + user.uid + " found ");
status = 'yes';
}
return status;
});
}
call this method by :
var result = await Service.doCallAuth('test', 'test');
I'm trying to check the entered username and password stored in a database.
My solution is not correct and I think there might be something better than my code.
Here it is thus far:
function login (username, password, callback) {
var query = "SELECT * FROM users WHERE username = ?";
connection.query(query, [username], function (err, results) {
if (err) return callback(err);
if (results.length === 0) return callback();
var user = results[0];
if (!bcrypt.compareSync(password, user.password)) {
return callback();
}
callback(null, {
id: user.id.toString(),
});
});
}
app.get('/salam', function (req, res) {
var username = 'mahdi';
var originalPassword = 'a';
login(username , originalPassword,function (callback) {
console.log(callback);
});
});
In my code, console.log(callback); returns null, but usernames and passwords are correct. How can I fix this?
In your success callback function, you are having 2 arguments but in error callback, only one argument.
In error and success case, value of first parameter will always be null and in if (!bcrypt.compareSync(password, user.password)) { case, value of first argument will be undefined as there is no value being passed as argument.
Suggestion: Use first argument as Boolean(false or true) and based on the value, handle the callback.
function login(username, password, callback) {
var query = "SELECT * FROM users WHERE username = ?";
connection.query(query, [username], function(err, results) {
if (err) return callback(false);
if (results.length === 0) return callback();
var user = results[0];
if (!bcrypt.compareSync(password, user.password)) {
return callback(false);
}
callback(true, {
id: user.id.toString(),
});
});
}
app.get('/salam', function(req, res) {
var username = 'mahdi';
var originalPassword = 'a';
login(username, originalPassword, function(success, value) {
if (success) {
console.log(value);
}
});
});
It should be, because you didn't pass anything in callback. Change like this :
function login (username, password, callback) {
var query = "SELECT * FROM users WHERE username = ?";
connection.query(query, [username], function (err, results) {
if (err) return callback(err);
if (results.length === 0) return callback(null, false);
var user = results[0];
if (!bcrypt.compareSync(password, user.password)) {
return callback(null, false);
}
callback(null, true, {
id: user.id.toString(),
});
});
}
app.get('/check', function (req, res) {
var username = 'mahdi';
var originalPassword = 'a';
login(username , originalPassword,function (err, result, id) {
console.log(err);
console.log(result);
console.log(id);
});
});
result is for finding out true|false of action. And id means when result is true
Also err for callback is needed to error handling
In my database.js I have
var Mysql = require('Mysql');
var Jwt = require('jsonwebtoken');
var bcrypt = require('bcrypt');
var supersecretkey = 'JMDub_Super_Secret_key';
var config = require('./config');
var signupErrors = require('./Signuperrors.js');
var sucessMsg = require('./SucessMessages.js');
var App_errors = require('./error.js');
var query = require('./queryDB.js');
var connection = Mysql.createConnection({
"host": "******",
"user": "****",
"password": "***",
"database": "***"
});
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
//Sign Up Methods
var createUser = function createwithCredentails(post,callback) {
bcrypt.hash(post.password, 10, function(err, hash){
//console.log('Cache Hash : +',hash);
var createUserQuery = connection.query('INSERT INTO users SET ?',{"email":post.email,"password":hash,"username":post.username},function(err,result){
if (err) {
if (err.code == 'ER_DUP_ENTRY') {
//console.log(err.code);
callback(signupErrors.error_5000);
}
else callback(App_errors.error_1003);
}
if (result) {
callback(sucessMsg.success_signup);
}
});
});
}
//connection.query('SELECT * FROM Users Where Username = '' AND Password = ''');
var validateUser = function ValidateUserWithUserNameAndPassword(post,callback) {
var UserCheckQuery = connection.query('SELECT * FROM users WHERE email="'+post.email+'"',function(err, results, fields) {
if (err){
console.log(err);
callback(App_errors.error_1000);
}
if (results.length == 1) {
//console.log(results[0].password,post.password);
var givenPassword = post.password;
var DBhash = results[0].password;
bcrypt.compare(givenPassword, DBhash,function(err, res) {
if (res) {
console.log('Password matched');
var token = Jwt.sign({"email":post.email,"username":post.username},supersecretkey, {
expiresIn: 60*60*5 // expires in 5 hours
});
callback({
message:{
"success":1,
"description":"sucessfully logged in - please cache the token for any queries in future",
"environment":"test",
"errorCode":null
},
"token":token
});
}
if (!res) {
console.log('password doesnt match');
callback(signupErrors.error_6000);
}
if (err) {
console.log('Error Comparing Passwords');
callback(App_errors.error_1004);
}
});
}
else{
callback(signupErrors.error_6000);
}
});
};
var isauthenticate = function isauthenticated(post,route,callback) {
if (post.headers.token) {
Jwt.verify(post.headers.token, supersecretkey, function(err, decoded) {
if (decoded) {
//console.log(decoded);
//From this part the user is Sucessully Authenticated and autherization params can be extracted from token if required
//Write Business Logic in future as per the requirement
//Operation 1 - Update Profile
//Profile Details consists of {1.first name 2.last name 3. profile pictur(base 64 encoded) 4.further settings in future that can be added to DB if required}
if (route == '/update-profile') {
query.updateProfile(connection,decoded.email,post.body,function(response) {
callback(response);
});
}
//callback({"message":"is a valid token"});
}
if (decoded == null) {
console.log('is not a valid token');
//callback(App_errors.error_1000);
}
if (err) {
console.log('error verifying token');
callback(App_errors.error_1000);
}
});
}
else{
callback(App_errors.error_1001);
}
};
module.exports = {
validateUser:validateUser,
createUser:createUser,
isauthenticate:isauthenticate,
connection:connection
}
I am exporting connection object to queryDB.js file. But when I try to log the exported connection object I get undefined object. Why is this happening?
When I pass connection object as function argument, everything works fine. Not sure why?
below is queryDB.js file
var errors = require('./error.js')
var Dbconnection = require('./Database.js').connection;
var updateProfile = function profiledata(connection,email,data,callback) {
console.log(Dbconnection);
if ((!data)|| (Object.keys(data).length < 1)) {
//console.log(data);
callback(errors.error_1001);
}
else{
callback({"message":"update Sucesss"});
//console.log(connection);
//var updateData = mapProfileDataTomodel(data);
//console.log(updateData);
connection.query('SELECT * FROM users WHERE email = "'+email+'"',function(err, result,feilds) {
if (err) throw err;
if (result) {
console.log(result);
}
});
}
}
var mapProfileDataTomodel = function mapProfileDataTomodel(data) {
var profileDataModel = {};
for (var key in data) {
//console.log('looping and mapping data');
if (data.firstname) {
profileDataModel.firstname = data.firstname;
}
if (data.lastname) {
profileDataModel.lastname = data.lastname;
}
if (data.profilepic) {
profileDataModel.profilepic = data.profilepic;
}
}
return profileDataModel;
}
module.exports = {
updateProfile:updateProfile
}
I have commented out connection object log via function arguments.
So, Why I am unable to get the connection object that is exported? But I used the same exported connection object in my app.js file. It did work fine there.
Here's what happening. I'm saving new companies first, then attaching the _id to each new user before they get saved. The issue I'm running into is returning a response. When I put the res.json() into the function thats getting repeated obviously I'm getting an error because I already have a response sent from the first time it loops through.
So, How do I call signupSeq(record, res) but wait for the async methods to finish so I know whether I have an error or not?
var signupSeq = function(req, res) {
async.waterfall([
function(callback) {
console.log(req);
if (req.company._id===undefined){
var company = new Company(req.company);
company.save(function(err){
if (err) {
console.log('save error');
callback(err);
}else{
callback(null, company._id);
}
})
}else{
callback(null, req.company._id); //pass teh plain ID if it's not a new name:xxx
}
},
function(companyId, callback) {
delete req.company
req.company = companyId
// Init Variables
var user = new User(req);
var message = null;
// Add missing user fields
user.provider = 'local';
user.displayName = user.firstName + ' ' + user.lastName;
// Then save the user
user.save(function(err) {
if (err) {
callback(err);
} else {
callback(null, user);
}
});
}
], function (err, result) {
if(err){
console.log(result+'funciton result')
return err
// res.status(400).send({
// message: errorHandler.getErrorMessage(err)
// });
}else{
console.log(result+'funciton result')
return result
//res.json(result)
}
});
}
exports.saveMany = function(req, res){
async.each(req.body, function(record, callback) {
// Perform operation on record.body here.
console.log('Processing record.body ' + record);
// Do work to process record.body here
var x = signupSeq(record, res)
console.log(x+'<<<<<<<value of x');
console.log('record.body processed');
callback();
}, function(err){
// if any of the record.body processing produced an error, err would equal that error
if( err ) {
res.json(err);
// One of the iterations produced an error.
// All processing will now stop.
console.log('A record.body failed to process');
} else {
res.json('Success');
console.log('All files have been processed successfully');
}
});
}
You could add a callback (cb) in your signupSeg function.
var signupSeq = function(req, res, cb) {
async.waterfall([
function(callback) {
console.log(req);
if (req.company._id===undefined){
var company = new Company(req.company);
company.save(function(err){
if (err) {
console.log('save error');
callback(err);
}else{
callback(null, company._id);
}
})
}else{
callback(null, req.company._id); //pass teh plain ID if it's not a new name:xxx
}
},
function(companyId, callback) {
delete req.company
req.company = companyId
// Init Variables
var user = new User(req);
var message = null;
// Add missing user fields
user.provider = 'local';
user.displayName = user.firstName + ' ' + user.lastName;
// Then save the user
user.save(function(err) {
if (err) {
callback(err);
} else {
callback(null, user);
}
});
}
], function (err, result) {
if(err){
console.log(result+'funciton result')
cb(err)
// res.status(400).send({
// message: errorHandler.getErrorMessage(err)
// });
}else{
console.log(result+'funciton result')
cb(null,result)
//res.json(result)
}
});
}
exports.saveMany = function(req, res){
async.each(req.body, function(record, callback) {
// Perform operation on record.body here.
console.log('Processing record.body ' + record);
// Do work to process record.body here
signupSeq(record, res,function(err,result){
var x= result;
console.log(x+'<<<<<<<value of x');
console.log('record.body processed');
callback();
})
}, function(err){
// if any of the record.body processing produced an error, err would equal that error
if( err ) {
res.json(err);
// One of the iterations produced an error.
// All processing will now stop.
console.log('A record.body failed to process');
} else {
res.json('Success');
console.log('All files have been processed successfully');
}
});
}
This way inside the asyn.each the signipSeg will have to finish before the call of the callback().
Hope this helps.
I'm trying to make a simple authentication with node js. Because I read user data from a database, I have to make it asynchronous. Here's my function, which checks if authentication is ok:
function auth(req, callback) {
var header = req.headers['authorization'];
console.log(cb.type);
console.log("Authorization Header is: ", header);
if(!header) {
callback(false);
}
else if(header) {
var tmp = header.split(' ');
var buf = new Buffer(tmp[1], 'base64');
var plain_auth = buf.toString();
console.log("Decoded Authorization ", plain_auth);
var creds = plain_auth.split(':');
var name = creds[0];
var password = creds[1];
User.findOne({name:name, password:password}, function(err, user) {
if (user){
callback(true);
}else {
callback(false);
}
});
}
}
And here I call the function:
auth (req, function (success){
if (!success){
res.setHeader('WWW-Authenticate', 'Basic realm="myRealm');
res.status(401).send("Unauthorized");
}else{
if(user!==req.user) {
res.status(403).send("Unauthorized");
}else{
User.findOneAndUpdate({user:userid}, {user:req.body.user, name:req.body.name, email:req.user.email, password:User.generateHash(req.body.password)},
{upsert:true}, function(err, user) {
if(!err) {
res.status(200).send("OK");
}else{
res.status(400).send("Error");
}
});
}
}
});
This gives me error "TypeError: object is not a function", pointing at "callback(false)". I have no idea what could cause this error, as I pass a function as a parameter, and the first log message prints "[function]". Any help would be appreciated.