nodejs- callback in modules not working - node.js

I am performing database connection in nodejs module. But its callback is not called.
Here is my module-
*getChapterList.js
var mysql=require('mysql');
var client=mysql.createClient({
user:'mysql',
password:''
});
client.useDatabase('test');
module.exports.get_chapter_list = function(subject_id){
client.query("select distinct chapter_id from course_associations where subject_id="+subject_id+" and status_id=1",
function(err,results,fields){
return results;
});
return "hello";
};
Now i am calling this module as-
rs=require('./getChapterList');
rs.get_chapter_list(1);
// Output: hello
but expected o/p is results array.
Googled alot.but no result..

The callback will be called after the query completes and the return value of results will be passed back to the method that created the callback, which then discards it.
The reason why the output is "hello", is because that's what the get_chapter_list function returns.
What happens is:
You call the get_chapter_list function
The client.query fires off a request to the database
The client.query function returns.
The get_chapter_list function returns "hello".
The SQL query completes and calls the callback
Your callback method is called and does nothing (it just returns the results, but that return value is handed back to the caller of the callback (somewhere within client.query) which discards it).
To get what you want you'll probably need to think asynchronously.
Define the method as
module.exports.get_chapter_list = function(subject_id, callback){
client.query("select distinct chapter_id from course_associations where subject_id="+subject_id+" and status_id=1",
function(err,results,fields){
// doesn't contain any error handling
callback(results);
});
};
and then call the method:
rs.get_chapter_list(1, function(results) {
console.log(results); // or whatever you need to do with the results
});

You need to return the results asynchronously:
exports.get_chapter_list = function(subject_id, callback) {
client.query("select ...", callback);
};
...
var rs = require('./getChapterList');
rs.get_chapter_list(1, function(err, results) {
if (err) {
// handle error
} else {
// do something with results
console.log(results);
}
});

scttnlsn answer is correct, as I have faced this issue and had solved by just passing the callback function as a argument.
Try for that:
var mysql=require('mysql');
var client=mysql.createClient({
user:'mysql',
password:''
});
client.useDatabase('test');
module.exports.get_chapter_list = function(subject_id, callback){
client.query("select distinct chapter_id from course_associations where subject_id="+subject_id+" and status_id=1",
function(err,results,fields){
callback( results );
});
return "hello";
};
And then
var rs = require('./getChapterList');
rs.get_chapter_list(1, function(results) {
console.log(results);
}
});
This will print the desire output.

Related

Express Mongoose Model.find() returns undefined

Hej, have a problem. Trying to send Express response with Mongo data in it.
This is code from my Express server
var Task = require('./modules/Task');
app.get('/get-all-tasks',function(req,res){
res.setHeader('Content-Type', 'application/json');
console.log(Task.getAllTasks()); // returns undefined
res.json({msg:"Hej, this is a test"}); // returns object
});
This is mongoose model in separate file
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/todo-app');
var TaskSchema = mongoose.Schema({
name: String,
assignee: String
},{ collection : 'task' });
var Task = module.exports = mongoose.model('Task', TaskSchema);
module.exports.createTask = function (newTask, callback) {
newTask.save(callback);
}
module.exports.getAllTasks = function(){
Task.find().lean().exec(function (err, docs) {
console.log(docs); // returns json
});
}
How can I properly send data from getAllTasks function?
That's looks correct, but your are forgetting about the Javascript's asynchronous behavior :). When you code this:
module.exports.getAllTasks = function(){
Task.find().lean().exec(function (err, docs) {
console.log(docs); // returns json
});
}
You can see the json response because you are using a console.log instruction INSIDE the callback (the anonymous function that you pass to .exec())
However, when you type:
app.get('/get-all-tasks',function(req,res){
res.setHeader('Content-Type', 'application/json');
console.log(Task.getAllTasks()); //<-- You won't see any data returned
res.json({msg:"Hej, this is a test"}); // returns object
});
Console.log will execute getAllTasks() function that doesn't return anything (undefined) because the thing that really returns the data that you want is INSIDE the callback...
So, to get it work, you will need something like this:
module.exports.getAllTasks = function(callback){ // we will pass a function :)
Task.find().lean().exec(function (err, docs) {
console.log(docs); // returns json
callback(docs); // <-- call the function passed as parameter
});
}
And the we can write:
app.get('/get-all-tasks',function(req,res){
res.setHeader('Content-Type', 'application/json');
Task.getAllTasks(function(docs) {console.log(docs)}); // now this will execute, and when the Task.find().lean().exec(function (err, docs){...} ends it will call the console.log instruction
res.json({msg:"Hej, this is a test"}); // this will be executed BEFORE getAllTasks() ends ;P (because getAllTasks() is asynchronous and will take time to complete)
});
I believe what you would need to do is return the docs in your getAllTasks function, but perhaps a better way to do it asynchronously using callbacks like so:
module.exports.getAllTasks = function(callback){
Task.find().lean().exec(function (err, docs) {
// If there is an error, return the error and no results
if(err) return callback(err, null)
// No error, return the docs
callback(null, docs)
});
}
And then inside your route you would do:
app.get('/get-all-tasks',function(req,res){
Task.getAllTasks(err, docs){
if(err) return res.json(error: err)
res.json(msg: docs);
}
});
I'm not sure if getAllTasks should be a mongoose static, in which case your model would look something like this:
TaskSchema.statics.getAllTasks = function (callback) {
return this.find().lean().exec(callback);
}

How to get data OUTSIDE a node.js query?

How do I get data from a query OUTSIDE the query in Node.JS?
I can get results printed to the console INSIDE the function but I can't get the data OUTSIDE to use in other places in my application.
this.getMyQuestion = function(id) {
var query = connection.query('select * from questions where id = ' + connection.escape(id), function(err, result) {
if(err) {
console.error(err);
return;
}
//console.log(result[0].question); //displays in console
return(result[0].question);
});
}
var test = this.getMyQuestion(1);
console.log(test) //returns undefined.
You're using an asynchronous function, so by the time you run the console.log(test) after calling your function, it hasn't finished running and hasn't returned anything yet.
That's what callbacks are for. You pass a callback to your function, and when it finishes execution, it calls that callback function instead of returning a value like it is now.
For example :
this.getMyQuestion = function(id, callback) {
var query = connection.query('select * from questions where id = ' + connection.escape(id), function(err, result) {
callback(null, result[0].question);
});
}
this.getMyQuestion(1, function(err, question){
// Do what you want
});
You can also promises to get data from async functions.

how can return value with require file in node js?

I am new to node.js , and use ari client.
I have two .js files that first one is required in second one. I have declared a variable in second one that must contain return value of first file but console.log(variable) is undefined although in first file return value is not null.
in first file :
var db = require("./database.js");
var service_info = db.select(connection,'select * from services where ivr_shortcode = ?',service);
console.log(service_info);
service_info is undefined;
in second file :
this.select = function (connection,query,data){
connection.query(query,[data],function(err, results){
if(err)
{
throw err;
}
else
{
return results;
}
});}
You cannot just return values from callback due to call being asynchronous, you should use another function to get the results:
// file 'database.js'
exports.select = function (connection, query, data, callback) {
connection.query(query, [data], callback);
}
Than in your main:
// I assume `connection` and `service` are defined somewhere before (like in your original code)
var db = require("./database.js");
var service_info = db.select(connection,'select * from services where ivr_shortcode = ?',service, function(err, service_info){
console.log(service_info);
});
P.S.
You should really read some docs and look into Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference to get better understanding of scope visibility and closures
To deal with such condition you needs to implement it using the async/await.
exports.select = async function (connection,query,data){
await connection.query(query,[data],function(err, results){
if(err){
throw err;
}else{
return
}
});
}
This will waits until you get the result. So undefined condition never arise.
you have to export select.
something like this :
exports.select = function (connection,query,data){
connection.query(query,[data],function(err, results){
if(err)
{
throw err;
}
else
{
return
}
});}

How to set a variable to a query? mongodb

How do I set a variable to a query? I am trying to use functions and callbacks in node.js to work through async, but I am not sure how to get a query to equal to a variable. What I am trying to do in this code is take a friend collection that belongs to a user and return the friends result(which I don't think I am doing correctly in the query insertAll) and then find the user's info for each of the query. And then return the results as a render. I am not sure how to call render either with this...
Here is my code:
exports.contactList = function(req, res) {
var insertFriend = function(data, callback) {
var friend = User.findById({_id: user.friendStatus.fuId}, function() {
callback(null, data);
}, friend);
};;
var insertAll = function(coll, callback) {
var queue = coll.slice(0),
friendX;
(function iterate(){
if(queue.length === 0) {
callback();
return;
}
friendX = queue.splice(0,1)[0];
insertFriend(friendX, function(err, friendX) {
if(err) {throw err;}
console.log(friendX + ' inserted');
process.nextTick(iterate);
});
})();
};
insertAll([Friend.findOne({userId: req.signedCookies.userid})], function(){
});
};
A Query object is returned if you do not pass a callback.
From http://mongoosejs.com/docs/queries.html:
When a callback function:
is passed, the operation will be executed immediately with the results passed to the
callback.
is not passed, an instance of Query is returned, which provides a special QueryBuilder
interface for you.

how to wait the end of the execution of a function

I have a main in nodejs for my program where I need to use my result calculated in a module, but my I don't have the right result.
var myJSONClient = {
"nombre" : "<nombre_cliente>",
"intervalo" : [0,0]
};
var intervalo = gestionar.gestion(myJSONClient,vector_intervalo);
console.log("intervalo: "+intervalo); //return undefined
And this is the module
var gestion = function(myJSON,vector_intervalo) {
var dburl = 'localhost/mongoapp';
var collection = ['clientes'];
var db = require('mongojs').connect(dburl, collection );
var intervalo_final;
function cliente(nombre, intervalo){
this.nombre = nombre;
this.intervalo = intervalo;
}
var cliente1 = new cliente(myJSON.nombre,myJSON.intervalo);
db.clientes.save(cliente1, function(err, saveCliente){
if (err || !saveCliente) console.log("Client "+cliente1.nombre+" not saved Error: "+err);
else {
console.log("Client "+saveCliente.nombre+" saved");
intervalo_final = calculate(vector_intervalo);
console.log(intervalo_final); //here I can see the right content of the variable intervalo_final
}
});
setTimeout(function(){
console.log("pause");
},3000);
console.log(intervalo_final); //result not correct
return intervalo_final;
}
exports.gestion = gestion;
I know that node execute my return without wait the end of my function, for this I can't see the right result, but how can I force my program to wait the end of my function?
I tried with the setTimeout function but wasn't the right way.
You must implement your function just like the other async functions from the API!
First step : give callback to function
var gestion = function(myJSON,vector_intervalo, callback) {
Second step : when the async process is over call callback passing the result (you don't need the return line)
console.log(intervalo_final); //here I can see...
callback(intervalo_final);
Step three: use your function in an async way
gestionar.gestion(myJSONClient,vector_intervalo, function(result){
console.log(result);
});
In async JS you can't return a value the way it seems you trying to do. You need to pass a callback function from your main program when calling gestionar.gestion() (you can add it as a third argument).
Your code sample won't work because function gestion() returns immediately, before intervalo_final content is set.
Something like this:
gestionar.gestion(myJSONClient,vector_intervalo, function callback(intervalo) {
// This is the callback function
console.log("intervalo: " + intervalo);
});
And then within the function:
var gestion = function(myJSON,vector_intervalo, callback) {
...
db.clientes.save(cliente1, function(err, saveCliente) {
if (err || !saveCliente) {
console.log("Client "+cliente1.nombre+" not saved Error: "+err);
if (callback) callback(); // execute callback function without arguments
}
else {
console.log("Client "+saveCliente.nombre+" saved");
intervalo_final = calculate(vector_intervalo);
console.log(intervalo_final);
if (callback) callback(intervalo_final); // your callback function will be executed with intervalo_final as argument
}
});
Also, I highly recommend reading some async javascript tutorial, like http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/
And Felix's Node.js Guide: http://nodeguide.com/

Resources