Proper usage of a callback handler in Node - node.js

I am trying to get data that is being returned in a callback but my callback function (callbackFunc()) is not being executed, probably due to the way I am approaching this.If someone would point me in the right direction I would be grateful.
Thanks
var url = 'mongodb://localhost:27017/bac';
var term = 'usa';
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
findDocument(term.toUpperCase(),'country_code', db, function() {db.close();});
});
function callbackFunc(data){
console.log("inside callbackFunc()...");
console.log(data);
}
var findDocument = function(term, field, db, callbackFunc){
var collection = db.collection('bac');
collection.findOne({'country_code' : term}, function(err, document){
assert.equal(err,null);
console.log("Found this matching record for "+term);
console.log(document);
callbackFunc(document);
});
}

Let see your code:
findDocument(term.toUpperCase(),'country_code', db, function() {db.close();});
You pass wrong callback function, you pass function() {db.close();}.
i think you want pass:
function callbackFunc(data){
console.log("inside callbackFunc()...");
console.log(data);
}
so plese use:
findDocument(term.toUpperCase(),'country_code', db, callbackFunc);

The callback function been called is not the defined callbackFunc
function callbackFunc(data){ console.log("inside callbackFunc()..."); console.log(data); }
but the
function() {db.close();}
Because you are passing in the function arguments.

Related

res.send() is running before nested function completes with value

The 'GetUsers' function is running and it returns the correct values as expected. However, res.send(users) is running before the nested function has completed with the value so it is undefined. I have tried doing the res.send(users) from inside the nested function but it doesn't recognize the function. I have also tried using return users but can't get it to work. Any help would be appreciated!
app.get('/GetUsers', function (req, res){
var url = 'mongodb://localhost:27017/users';
var users = "";
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
console.log('Connection established to', url);
// Get the documents collection
var collection = db.collection('users');
// Get some users
collection.find().toArray(function (err, res) {
if (err) {
console.log(err);
} else {
console.log('Got Information from db.');
}
//Close connection
db.close();
console.log('db closed.');
users = res;
console.log(users);
});
}
});
res.send(users);
});
Just move res.send(users) inside your callback before/after you call console.log(users).
You reused the variable res in the toArray call, so please rename it there: ...toArray(function (err, res)... to ...toArray(function (err, result)... and also in users = res; to users = result;.
this is async call it will send the response and will not wait for the database connection function.
write res.send in call back function
write your res.send function where you are closing your data base connection.
here is detail How do I return the response from an asynchronous call?
Found the answer!!!
I needed to use res.send(users) in my callback after I had closed the database as pointed out by the users suggestions above. HOWEVER, that alone wasn't working as res.send(users) was erroring as it wasn't recognized as a function. I had to use res.send({'matched':users}) and then access my response objects on the client side like this: response.matched.objects etc.
Thanks for your help everyone!

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 properly export/require

I'm trying to export one function this way:
exports.query = function(request){
conn.query(request, function(err, rows, fields){
if(err) console.log(err);
return rows[0].id;
});
}
and using it:
var mysql = require('./mysql');
console.log(mysql.query('SELECT * FROM tablename'));
Proceeding this way for getting a result involves undefined as output.
How do I to fix this, please?
Note that when I just type console.log(rows[0].id) instead of return rows[0].id it sends back 123.
Thanks in advance!
In your example, the output is being returned to the anonymous function of the database query instead of the caller of the module. You can use a callback to return output to the caller of the module.
exports.query = function(request, callback){
conn.query(request, function(err, rows, fields){
if (err) {
callback(err);
} else {
callback(null, rows[0].id);
}
});
}
Then call it like
var mysql = require('./mysql');
mysql.query('SELECT * FROM tablename', function(err, results){
if (err) {
console.error(err);
} else {
console.log(results);
}
});
That's a problem of synchrony.
the conn.query function returns undefined because it finish its execution before the results are fetched (like almost any i/o related operation on js/node).
One possible solution to that, is to provide a callback to your query function.
exports.query = function(request, cb){
conn.query(request, function(err, rows, fields){
// some "special" processing
cb(err, rows, fields);
});
};
If you're not familiar with async functions, take a look on some articles about that:
http://justinklemm.com/node-js-async-tutorial/
https://www.promisejs.org/

module always returns null no matter what

I am new to node.js and was wondering why my code always return null.
I have db.js
exports.getItems = function(){
var conn = mysql.createConnection();
conn.connect();
conn.query("Select * From Items", function(err, rows, fields) {
if (err) throw err;
conn.end();
return rows;
});
};
and the module is called like this:
var db = require('../db.js');
exports.items = function(req, res){
var data = db.getItems();
console.log('second', data);
res.end(data);
};
and route:
app.get('/api/items', api.items);
The console.log('second') is always "second undefined". I have verified that the query is return items in the rows.
Please advice.
Classic async problem.
getItems is going to return before the database query is done. The data from the database is returned in the callback, not in the function itself.
When you write:
var data = db.getItems();
console.log('second', data);
res.end(data);
the value for data is undefined because you don't have a return statement inside getItems! So getItems returns undefined, as per the rules of JavaScript.
What you need is something like (and please understand I have not tested this) is:
exports.items = function(req, res){
var conn = mysql.createConnection();
conn.connect();
conn.query("Select * From Items", function(err, rows, fields) {
conn.end();
if (err) throw err;
res.end(rows);
});
}
See various sites online for managing connections cleanly. But this should be enough to get you to understand that the response should be sent from the callback of query which is where the data is actually available.

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.

Resources