function returning values as undefined in nodejs - node.js

I am working on a NodeJs project for the first time. And now i am stuck with the function returning values through JS and getting values to use in express.
var dbitems = "before fn";
function refreshData(callback) {
db.open(function (err, db) {
if (!err) {
db.collection('emp').find().toArray(function (err, items) {
dbitems = items;
callback(JSON.stringify(items));
});
}
else {
console.log("Could not be connnected" + err);
dbitems = {"value":"not found"};
}
});
}
}
refreshData(function (id) { console.log(id); });
This function retrieves values perfectly from refreshData and writes into console. But what I need is to use the retrieved value to send into express html file from this function by "returnedData"
exports.index = function (req, res) {
var valrs = refreshData(function (id) {
console.log(JSON.parse(id)); ---this again writes data perfectly in the console
});
console.log(valrs); -------------------but again resulting in undefined
res.render('index', { title: 'Express test', returnedData: valrs });
};
Any help would be appreciated.
Thanks & Regards,
Luckyy.

You need to render this after the database request finishes.. so it needs to be called from within the callback.
exports.index = function (req, res) {
refreshData(function (id) {
res.render('index', { title: 'Express test', returnedData: JSON.parse(id) });
});
};
it's asynchronous so you can't just put values in order, needs to go through the callbacks.

Related

res is not defined in Node.js (Mongoose)

How can I put res in a normal function i.e not an exported one which is not part of routes?
function createNewStudent(v,callBackOne){
if (callBackOne) {
studentInfo.callBackOneStudent = callBackOne;
}
// common filter json
var filterjson = common.defaultFilterJson();
filterjson['active'] = true;
filterjson['email'] = v.email;
// student initialization
var student = new Student(v);
async.waterfall([
function (done) {
student.save(function (err) {
if (!err) {
studentInfo.callBackOneStudent();
Employee.update({_id: student.created_by},{"$push": { "students": student._id } }).exec(function (err, employee) { });
done();
}
});
}
}
});
},
function (done) {
var url = config.mailer.studentActivateUrl + student._id;
---error is here-----
res.render('modules/users/server/templates/student-confirmation-email', {
name: student.first_name + ' ' + student.last_name,
appName: 'GAIPP',
url: url
}, function (err, emailHTML) {
done(err, emailHTML, student);
});
}
});
My error is 'res' is not defined. Can anyone please help me to solve this error?
The only way that you can put res in a function is if you somehow supply it to that function at runtime. Remember that res is meaningful only in request handling. Outside of the request handler your function couldn't even know which request to respond to because there might be several requests served at the same time.
If you want to have a function that has access to res then you have those options:
Use a nested function in your request handler, e.g.
app.get('/foo', function (req, res) {
function x() {
// you can use res here
}
x();
});
Add res as an argument:
function x(res) {
// you can use res here
}
app.get('/foo', function (req, res) {
x(res);
});
Another option would be to add a callback to your function that would be passed by the handler:
function x(args, cb) {
// you cannot use res here
// but you can call the callback:
cb(null, 'something');
}
app.get('/foo', function (req, res) {
x(function (err, data) {
if (err) {
// handle error
}
// use res here with data supplied by x()
res(data);
});
});
Instead of using callback your x() function could also return a promise.

How do I return my data from a function?

I've written a small database function that gets some data from the DB and puts it into the format that I want, but I'm having difficulties returning the data to display it with Express. The database function is as follows:
function getAllEvents(req, res, next) {
db.any('select * from sensors, events where sensors.sensorid = events.sensorid')
.then(function (data) {
var final = [];
data.forEach(function(datas){
if (!final[datas.sensorid]){
final[datas.sensorid] = {};
}
if (!final[datas.sensorid].name){
final[datas.sensorid].name = datas.name;
final[datas.sensorid].signatures = {};
}
if (!final[datas.sensorid].signatures[datas.signature]){
final[datas.sensorid].signatures[datas.signature] = {};
final[datas.sensorid].signatures[datas.signature].id = "sen" + datas.sensorid + "sig" + datas.signature;
final[datas.sensorid].signatures[datas.signature].signature = datas.signature;
final[datas.sensorid].signatures[datas.signature].message = datas.message;
final[datas.sensorid].signatures[datas.signature].events = {};
}
final[datas.sensorid].signatures[datas.signature].events[datas.eventid] = datas;
})
return final;
})
.catch(function (err) {
console.log("Something went wrong! ", err)
});
}
And the router function to call it is this:
router.get('/events', function(req, res, next) {
db.getAllEvents(function(err, data){
res.render('events', { data: data });
});
});
I think the router function is waiting indefinitely for the data though as I get no errors but the page never loads. What am I doing wrong?
What am I doing wrong?
This code:
router.get('/events', function(req, res, next) {
db.getAllEvents(function(err, data){
res.render('events', { data: data });
});
});
is ok besides the fact that you are not checking for errors. Notice that getAllEvents is expecting a function as an argument.
now Let's look at your getAllEvents function prototype
function getAllEvents(req, res, next) {
It is simply not correct and should have been something like
function getAllEvents(callback) {
Then you would be able to call the callback and "return" the result like this
return callback(null,data);
or if an error occurred during you database connection pass the error to the callback
return callback(err);

NodeJS callback - Access to 'res'

I am using the Express framework and I have the following in one of my route files:
var allUsersFromDynamoDb = function (req, res) {
var dynamodbDoc = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: "users",
ProjectionExpression: "username,loc,age"
};
dynamodbDoc.scan(params, function (err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err));
res.statusCode = 500;
res.send("Internal Server Error");
} else {
console.log("DynamoDB Query succeeded.");
res.end(JSON.stringify(data.Items));
}
});
}
I am using the above function in one of my routes:
router.get('/users', allUsersFromDynamoDb);
Now the callback that I am defining while making a call to the "scan" on dynamodbDoc can be pretty useful if defined as a separate function. I can re-use that for some of my other routes as well.
But how can I can still get access to the "res" inside this new function?
I think I should be using "closure" but I can't seem to get it exactly right. I think I would need to maintain the signature of the new callback function to expect 2 params, "err" and "data" as per the following page:
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#scan-property
Any ideas on how this can be done?
You can use that function as middleware of every routes you want http://expressjs.com/en/guide/using-middleware.html
The new route with the middleware:
var middlewares = require('./middlewares'),
controllers = require('./controllers');
router.get('/users', middlewares.allUsersFromDynamoDb, controllers.theRouteController);
The middleware (middlewares.js) where you pass your data to req so you can use that data everywhere you have req:
exports.allUsersFromDynamoDb = function (req, res, next) {
var dynamodbDoc = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: "users",
ProjectionExpression: "username,loc,age"
};
dynamodbDoc.scan(params, function (err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err));
next("Internal Server Error");
} else {
console.log("DynamoDB Query succeeded.");
req.dataScan = JSON.stringify(data.Items);
next();
}
});
};
And finally the controller (controllers.js):
exports.theRouteController = function (req, res) {
// Here is the dataScan you defined in the middleware
res.jsonp(req.dataScan);
};
Based on Michelem's answer here I tried something which makes things a bit cleaner and code more reusable:
var allUsersFromDynamoDb = function (req, res, next) {
var dynamodbDoc = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: "users",
ProjectionExpression: "username,loc,age"
};
dynamodbDoc.scan(params, function (err, data) {
req.err = err;
req.data = data;
next();
});
}
Now I declare another function:
var processUserResults = function (req, res, next) {
if (req.err) {
console.error("Unable to query. Error:", JSON.stringify(req.err));
res.statusCode = 500;
res.send("Internal Server Error");
} else {
console.log("DynamoDB Query succeeded.");
res.end(JSON.stringify(req.data.Items));
}
};
And finally this:
router.get('/users', [allUsersFromDynamoDb, processUserResults]);
All I need to do in the original "function(err, data)" callback is always set 2 values:
req.err = err
req.data = data
And call next(). And processUserResults can similarly be used for other routes.
Still curious to find out if there are any other efficient solutions.

Get monk to play well with Q.all

I have a collection of posts and a collection of users. When returning the list of posts, I want to resolve the references to users. This means making an async call for every row of the users. When monk returns a promise, it returns something that responds to "complete" or "success". Q expects something responding to "then". I need to use Q.all to wait for all the users to be fetched into the posts, but I can't make it play well with monk's promise style.
Here is my attempt.
exports.posts = function (req, res) {
req.posts.find()
.complete(function(err, posts) {
handle(err, res, posts);
var postsWithUsers = posts.map(function(post) {
return req.users.findOne({_id: post.userId}).complete(function(err, result) {
post.user = result;
});
});
Q.all(postsWithUsers.map(function(monkPromise) {
monkPromise.then = monkPromise.complete
}), function(err, results) {
console.log("done with all posts");
});
});
};
Just for everyone else out there. This is one solution, perhaps not the best.
exports.posts = function (req, res) {
req.posts.find()
.complete(function(err, posts) {
handle(err, res, posts);
var postsWithUsers = posts.map(function(post) {
var deferred = Q.defer();
return req.users.findOne({_id: post.userId}).complete(function(err, result) {
post.user = result;
deferred.resolve(result);
});
return deferred.promise;
});
Q.all(postsWithUsers, function(err, results) {
console.log("done with all posts");
});
});

console.log a GET request with Node.js

I'm using the Express framework for my node application. I'm quite new to it so I thought I'd create a defacto "To-Do" application to learn about it. What I'm trying to do it log a request made for debugging purposes. So when I go to:
app.get('/todos/:id', function (req, res) {
var result = db.load(req.params.id);
result ? res.send(result) : res.send(404);
});
I want to a) see what result equals and b) log what happens in my db.load method:
exports.load = function (id) {
todos.findOne({ id: id }, function (err, todo) {
if (!err) {
return todo;
}
});
}
I'm using the mongolian library to access my MongoDB data. I've followed an example by Steve Sanderson: https://github.com/SteveSanderson/nodejs-webmatrix-video-tutorials
app.get('/todos/:id', function (req, res) {
db.load(req.params.id, function(err, result) {
// also handle err
result ? res.send(result) : res.send(404);
});
});
exports.load = function (id, callback) {
todos.findOne({ id: id }, callback);
}

Resources