Callback Function returns undefined somehow [duplicate] - javascript

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

Return value from callback in TypeScript [duplicate]

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');

NodeJs check username and password return null

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

Exporting Mysql Connection in nodeJS

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.

async.each cannot set headers after already set

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.

Node js custom callback function error

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.

Categories

Resources