Node.JS / JavaScript Async Call back issue - node.js

I am trying to accomplish the following (should be quite basic and I must be missing something trivial):
Call a function with string that has a select statement
Wait until the DB call completes and the rows (or json equivalent) is returned
Populate http object to return back
Here is code:
util.js
exports.execute = function( query){
if (connection) {
connection.query(query, function(err, rows, fields) {
if (err) throw err;
console.log("from Util - " + JSON.stringify(rows));
return JSON.stringify(rows);
});
}
};
repo.js
var q = "select * from xxx";
var response;
util.execute(q, function (err, r){
if (err){
throw err;
console.log(err);
}
else {
console.log(r);
res.contentType('application/json');
res.write(r);
res.end();
}
});
My problem is while the code within util.js is called and I can see the json in console, it never comes back to the anonymous call back function in the repo.js.
What am I doing wrong here ?
Update
Thanks Ben
I also found the solution in same line ... here is new code:
repo.js:
var send_data = function (req, res, r){
res.contentType('application/json');
res.write(r);
res.end();
}
exports.all = function(req, res){
var q = "select * from XXX";
var response;
util.execute(req, res,q, send_data);
};
util.js:
exports.execute = function(req, res, query, callback){
if (connection) {
connection.query(query, function(err, rows, fields) {
if (err) throw err;
callback(req, res, JSON.stringify(rows)) ;
});
}
};

util.execute only accepts one parameter in your code. It needs to accept a second callback parameter in order to use it the way you do. (Callbacks aren't magic, they're just function calls)
Something like:
exports.execute = function(query,callback){
if (connection) {
connection.query(query, function(err, rows, fields) {
if (err) throw err;
console.log("from Util - " + JSON.stringify(rows));
callback(null,JSON.stringify(rows));
});
}
};
If you'd like it to behave consistently and accept an error parameter, you might want fill that in:
exports.execute = function(query,callback){
if (connection) {
connection.query(query, function(err, rows, fields) {
callback(err,null);
console.log("from Util - " + JSON.stringify(rows));
callback(null,JSON.stringify(rows));
});
}
};

Related

NodeJS request not returned

Swagger Inspector
This is the source code
API.js
router.post('/curriculum2_section/', (req,res)=> {
curriculum2_section.CREATE(req.body.curr2_section,req.body.curr2_id,req.body.curr2_section_student_amount)
})
curriculum2_section.js
module.exports.CREATE = function CREATE(curr2_section,curr2_id,curr2_section_student_amount) {
var sqlString = `INSERT INTO curriculum2_section(curr2_id,curr2_section,curr2_section_student_amount)VALUES('${curr2_id}',${curr2_section},${curr2_section_student_amount})`
pool.getConnection((err, conn) => {
if(err) throw err
pool.query(sqlString, function (err, rows) {
console.log('Query String:\n '+this.sql);
if(err) throw err
console.log('Data Insert: '+curr2_section+','+curr2_id+','+curr2_section_student_amount)
conn.release();
})
})
}
I've tried using the callback but it doesn't work. I think it because I don't understand how to use it
Please help me
You need to pass the data you want to output to a method on res in order to get output from Express.
Given what you have here, your best bet might be to add a callback as the last parameter of curriculum2_section.CREATE and use that callback to pass data to res.
https://expressjs.com/en/4x/api.html#res
router.post('/curriculum2_section/', (req,res)=> {
curriculum2_section.CREATE(req.body.curr2_section,req.body.curr2_id,req.body.curr2_section_student_amount, (err, data) => {
res.send(data);
});
});
module.exports.CREATE = function CREATE(curr2_section,curr2_id,curr2_section_student_amount, cb) {
var sqlString = `INSERT INTO curriculum2_section(curr2_id,curr2_section,curr2_section_student_amount)VALUES('${curr2_id}',${curr2_section},${curr2_section_student_amount})`
pool.getConnection((err, conn) => {
if(err) throw err
pool.query(sqlString, function (err, rows) {
console.log('Query String:\n '+this.sql);
if(err) throw err
console.log('Data Insert: '+curr2_section+','+curr2_id+','+curr2_section_student_amount)
conn.release();
cb(null, 'Data Insert: '+curr2_section+','+curr2_id+','+curr2_section_student_amount);
})
})
}

Node JS res.send not a function

i'm trying create first node js api.
i wroted this code but when i start server.js it's not working.
here code :
var executeQuery = function(res, query){
sql.connect(dbConfig, function (err) {
if (err) {
console.log("Error while connecting database :- " + err);
res.send(err);
}
else {
// create Request object
var request = new sql.Request();
// query to the database
request.query(query, function (err, res) {
if (err) {
console.log("Error while querying database :- " + err);
res.send(err);
}
else {
res.send(res);
}
});
}
});
}
when i start it error say :
C:\node\atlasErpApi\server.js:47 res.send(res);
TypeError: res.send is not a function at C:\node\atlasErpApi\server.js:47:43
You are declaring a new variable res as argument to your request.query callback which shadows the res the comes as argument to your executeQuery function.
This should be most obvious at the line res.send(res) which, if you think about it, doesn't make sense at all.
Use different variable names for the two. For example, change the inner one to sqlRes:
var executeQuery = function(res, query) {
sql.connect(dbConfig, function(err) {
if (err) {
console.log("Error while connecting database :- " + err);
res.send(err);
} else {
// create Request object
var request = new sql.Request();
// query to the database
request.query(query, function(err, sqlRes) { // <<< CHANGED to sqlRes
if (err) {
console.log("Error while querying database :- " + err);
res.send(err);
} else {
res.send(sqlRes); // This makes more sense now :-)
}
});
}
});
}
Note: Technically this also happens for err - you have an err from request.query's callback shadowing the err from sql.connect's callback. But this usually doesn't matter because you won't need to use the outer err in the inner callback.

Why does my function lose its return value? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
Good afternoon, I'm now learning nodeJS. Right now I have a problem with a function I devised and I can't seem to find the problem
var http = require('http');
var mysql = require('mysql');
var url = require('url');
http.createServer(function (req, res) {
if (req.url === '/favicon.ico') {
//res.writeHead(200, {'Content-Type': 'image/x-icon'} );
res.end();
//console.log('favicon requested');
return;
}
var con = mysql.createConnection({
host: "localhost",
user: "admin",
password: "admin",
database: "brandibDB"
});
res.writeHead(200, {'Content-Type': 'text/plain'});
var addr = url.parse(req.url, true);
var teste = addr.pathname.split('/');
var tester = getJson(teste,con);
console.log(tester);
//console.log(teste);
//res.write(teste[1] + teste[2]);
res.end();
}).listen(8080);
function getJson(teste,con){
var resultado = "";
con.connect(function(err){
if (err) throw err;
if(teste[1] == 'users'){
if(teste.length!=2){
var str = "SELECT * FROM tblUsers where id ="+ mysql.escape(teste[2]) + "";
con.query(str, function (err, result, fields) {
if (err) throw err;
resultado = JSON.stringify(result);
});
}
else{
var str = "SELECT * FROM tblUsers";
con.query(str, function (err, result, fields) {
if (err) throw err;
resultado = JSON.stringify(result);
});
}
}
});
con.end;
return resultado;
}
console.log('Isto deve ser uma consola');
right now I have data in a db and I'm testing accessing this server with url: "localhost:8080/users/1" or "localhost:8080/users/"
When I run the second link for example, it should go into the function getJson and return the right value(a json with all the user registries) but it just returns empty. I've tried putting console logs inside the function around the lines "resultado = Json..." and it displays the right value. The result is lost afterwards.
Any tips?
It's because your getJson function has returned before the asynchronous callback from the query has completed, therefore resultado is still an empty string.
Instead you could either provide a callback to getJson that gets called when the query returns, or better still, use promises. Something like this:
var tester = getJson(teste, con)
.then(result => {
console.log('the results were:', results)
})
.catch(err => {
console.log('Something went wrong', err);
});
and your function becomes something like:
function getJson(teste, con) {
return new Promise((resolve, reject) => {
con.connect(function (err) {
if (err) throw err;
if (teste[1] == 'users') {
if (teste.length != 2) {
var str = "SELECT * FROM tblUsers where id =" + mysql.escape(teste[2]) + "";
con.query(str, function (err, result, fields) {
if (err) return reject(err);
return resolve(JSON.stringify(result));
});
} else {
var str = "SELECT * FROM tblUsers";
con.query(str, function (err, result, fields) {
if (err) return reject(err);
return resolve(JSON.stringify(result));
});
}
}
});
})
}
I'd also recommend ditching var and using let and const, it's much easier to keep track of your variable scopes that way.

Node js nested async call

I want to do async call from my getData function to getImage function but i am unable to get return data from getImage().Since the getData() does't wait for the completion of getImage(),as getImage() has further async db calls and therefore getData() always returns undefined.
What is the best way to do this instead doing nested callbacks?
var getData = function(id){
async.series([
function(callback){
var res = getImages(id);
callback(null, res);
}
],
// optional callback
function(err, results){
if (err) {
console.log("ERROR : " + err);
}else
{
console.log("Result: "+results);
}
});
}
var getImages = function(id){
async.series([
function(callback){
Image.find({id: id }).exec(
function(err, image) {
if (err) {
console.log(err);
callback(err, 0);
}else
{ console.log("Count: "+ image.length);
callback(null, image);
}
});
}
],
// optional callback
function(err, results){
if (err) {
console.log("ERROR : " + err);
}else
{
return results;
}
});
}
getData(1);
As you said you need to wait for getImages() to return, and you do that using promises.
Use any promise library, like q for instance:
var q = require('q')
...
var getImages = function(id){
var deferred = q.defer();
...
//do async logic that that evaluates some res obj you wish to return
db.find(..., function() {
deferred.resolve(res);
}
return deferred.promise;
}
Then, from getData(), you call it in the following matter:
getImages(id).then(
function(res) {
callback(null, res);
},
function(err) {
console.log("error:" + err);
}
);
As you are already using async - just use the waterfall functionality: https://github.com/caolan/async#waterfalltasks-callback
This way you will be able to run functions one after another and wait for the previous to finish, while still getting it's return value.

Node/Express function and callback are not breaking with return

I am creating a 'refresh data' function in Node and I cannot figure out where to place the callbacks and returns. The function continues to run. Below is a list of things the function should do. Could someone help out?
Check if a user has an api id in the local MongoDB
Call REST api with POST to receive token
Store token results in a MongoDB
Terminate function
./routes/index.js
router.post('/refresh', function(req, res) {
var refresh = require('../api/refresh');
refresh(req, function() { return console.log('Done'); });
});
../api/refresh.js
var callToken = require('./calltoken');
var User = require('../models/user'); // Mongoose Schema
module.exports = function(req, callback) {
User.findOne( {'username':req.body.username}, function(err, user) {
if(err) { console.log(err) }
if (user.api_id == 0) {
callToken.postToken(req.body.username, callback);
} else { // Do something else }
});
};
./calltoken.js
var request = require('request');
var Token = require('../models/token'); // Mongoose Schema
module.exports = {
postToken: function(user, callback) {
var send = {method:'POST', url:'address', formData:{name:user} };
request(send, function(err, res, body) {
if(err) { console.log(err) }
if (res.statusCode == 201) {
var newToken = new Token();
newToken.token = JSON.parse(body).access_token['token'];
newToken.save(function(err) {
if(err) { console.log(err) }
return callback();
});
}
});
}
};
I'm not an expert in Express but everywhere in you code in lines with if(err) { console.log(err) } you should stop execution (maybe of course not - up to you app) and return 400 or 500 to client. So it can be something like
if(err) {
console.log(err);
return callback(err); // NOTICE return here
}
On successful execution you should call return callback(null, result). Notice null as a first argument - it is according nodejs convention (error always goes as first argument).

Resources