Display of data on view from route.js - node.js

// This is my router.js
router.get('/restful', function(req, res){
console.log("before");
User.show_deatils(req, res, function(err, resultArray){
if(!err){
req.session.resultArray=resultArray;
req.session.save();
}
});
//console.log(req.session.resultArray)
res.render('restful',{resultArray:req.session.resultArray});
});
//This is model.js
module.exports.show_deatils=function(req,res,callback){
var resultArray=[];
mongo.connect(url,function(err,db){
assert.equal(null,err);
var cursor=db.collection('users').find();
cursor.forEach(function(doc,err){
assert.equal(null,err);
resultArray.push(doc);
callback(null, resultArray);
});
});
}
//I want to display the resultArray on loading view(restful.ejs).But the problem is when I first redirect to the page.It is not showing any value.But upon clicking the same page its been showing me the details.What I feel is on the first load it is not storing the values in session.How can we solve this issue?I am trying this for long time.

That is because you are rendering outside the async callback function
Change your code like this
router.get('/restful', function(req, res){
console.log("before");
User.show_deatils(req, res, function(err, resultArray){
if(!err){
req.session.resultArray=resultArray;
req.session.save();
res.render('restful',{resultArray:req.session.resultArray});
}
});
//console.log(req.session.resultArray)
});
It is storing correct in the session, that part is working but since the first time you are rendering outside the async callback, it has no value.

Related

user.save() does not save (does nothing) in mongodb

I'm trying to save a user in MongoDB, but it doesn't seem to work. I have no idea why. All i can tell you is that, the code is running and going in the .pre save function but it doesn't enter in the save function promise.
Can you tell me why it is not saving in base ?
Front submit function
handleSubmit(user){
console.log(user);
axios.post('http://localhost:3000/signup', user)
.then(data => {
console.log(data);
console.log("OBVIOUSLY I DON'T SEE THIS LOG EITHER");
}
);
}
app.js (node.js file)
app.post('/signup', urlencodedParser, function(req, res){
let user = new User(req.body);
user.save().then(() => {
console.log("I DON'T SEE THIS LOG");
});
res.end();
});
user.js (node.js file)
UserSchema.pre("save", (next) => {
console.log(this);
console.log("I SEE THIS LOG");
next();
});
const User = mongoose.model('user', UserSchema);
module.exports = User;
maybe a stupid question, but isn't your User in app.js undefined ?
maybe console.log the req.body. because i do not think you are making a user to begin with.
another tip :
use mongoose's create function instead, you will find a example under construction documents:
https://mongoosejs.com/docs/models.html
instead of .then() on your app.js try using a callback.
user.save(function(err, res){
if (err){throw err;}
console.log('test me', res)
})
You are closing your request before the user being saved.
move the res.end() into then function to solve the problem.
Or you can make an async function(req, res) and put await before user.save(), remove then and wait for database to response, like below:
app.post('/signup', urlencodedParser, async function(req, res) {
let user = new User(req.body);
await user.save();
res.end();
});

Undefinded error

route.js
router.get('/restful', function(req, res){
console.log("before");
User.show_deatils(req, res, function(err, resultArray){
if(!err) {
req.session.resultArray=resultArray;
}
});
console.log(req.session.resultArray);
res.render('restful',{resultArray:req.session.resultArray});
});
I don't know why I am getting as undefined when I am doing it console.log() in the above position.If I do console.log() just after the req.session.resultArray=resultArray then we are getting the result array.
I want to display this resultArray in my view.ejs. Can anyone suggest me how to solve it.What is the thing I am missing it out?
The console.log runs before the async function actually gets the details from the database. so you get undefined.
Do the render inside the callback. i.e, after you assign result array to session.
router.get('/restful', (req, res, next) {
User.show_deatils(req, res, function(err, resultArray) {
if(!err) {
req.session.resultArray=resultArray;
return res.render('restful' {resultArray:req.session.resultArray}));
}
});
});
Just do like this
router.get('/restful', function(req, res){
console.log("before");
User.show_deatils(req, res, function(err, resultArray){
if(!err) {
res.render('restful',{resultArray:resultArray});
}
});
});
I think this is what you want.

NodeJS extra field with byId();

Currently I am working on a nodeJS API, I have a model, and that model can have Media items, as you can see in my code here:
router.get('/:id', function(req, res, next) {
qbuilder.byId(Model,req)
.exec(
function(err,model){
Media.count({'model.entity': model._id}, function(err, media){
if(media){
console.log(media);
}
});
model.total_media = 15;
responders.sendJsonOrError(err, res, model, next);
});
});
Problem is, that the code:
model.total_media = 15;
Is not showing up in the responder, which is strange, because if I clean the object with: model = []; it returns empty.
Once I add lean() to my query, it returns the total_media in the responder, but then I get the problem that when I do like this:
router.get('/:id', function(req, res, next) {
qbuilder.byId(Model,req)
.exec(
function(err,model){
Media.count({'model.entity': model._id}, function(err, media){
if(media){
model.total_media = media;
}
});
responders.sendJsonOrError(err, res, model, next);
});
});
It is not populating the total_media, is there any other way to do this correctly?
Try with this. The response is sending before you assign values.
router.get('/:id', function(req, res, next) {
qbuilder.byId(Model,req)
.lean().exec(
function(err,model){
Media.count({'model.entity': model._id}, function(err, media){
if(media){
model.total_media = media;
}
responders.sendJsonOrError(err, res, model, next);
});
});
});

Distinguish Between Request Parameters in the same position?

Is there a way to distinguish between request parameters in the same position in expressjs?
E.g., is there a way to have:
router.get('/pages/:id', function(req,res){
var id=req.params.id;
api.getPagebyID(id, function(err,pageData){
if (err) console.log(err);
console.log(pageData);
});
});
And to have:
router.get('/pages/:name', function(req,res){
var name=req.params.name;
api.getPagebyName(name, function(err,pageData){
if (err) console.log(err);
console.log(pageData);
});
});
You can certainly set multiple middlewares for a particular pattern, but it's up to you to decide when to skip a middleware (with next). After a response is sent, no further middlewares are executed.
router.get('/pages/:id', function(req, res, next){
var id=req.params.id;
api.getPagebyID(id, function(err,pageData){
console.log(pageData);
if (err){
console.log(err);
if(err.error === 'not_found'){
// No id. Try name:
next();
} else {
// Actual error:
res.status(500).send();
}
}
});
});
router.get('/pages/:name', function(req,res){
var name=req.params.name;
api.getPagebyName(name, function(err,pageData){
if (err) console.log(err);
console.log(pageData);
});
});
If ID is a number, you can use regex to only match numbers:
router.get('/user/:id([0-9]+)', function(req, res){
res.send('user ' + req.params.id);
});
router.get('/range/:range(\\w+\.\.\\w+)', function(req, res){
var range = req.params.range.split('..');
res.send('from ' + range[0] + ' to ' + range[1]);
});
Check out the docs here: http://expressjs.com/4x/api.html#router.param

Use Async lib in nodejs

Hello guys here is my code:
function get_group(req, res, next) {
var send_result = function(err, group_list) {
[...]
res.send(group_list);
return next();
};
Group.findOne({'_id': req.params._id}, send_result);
}
Now how can I implement the async library (caolan) using async.series and combine the findOne() with send_result, the code as it is look pretty disorganised to me.
EDIT1:
I used this strategy but I am not sure is correct, any suggestion?
function get_group(req, res, next) {
async.waterfall([
function(callback) {
Group.findOne({'_id': req.params._id}, callback);
}
],
function (err, group_list){
res.send(group_list);
return next();
});
}
Any suggestion?
For what they call routes in Express.js you actually almost never need to use the async library. The reason is that routes are actually a sort of control flow them self. They take as many middleware as you want so you can divide your routes into small blocks of code.
For example lets say you want to get one record/document from a database do something with it and then send it as json. Then you can do the following:
var getOne = function(req, res, next){
db.one( 'some id', function(err, data){
if (err){
return next( { type: 'database', error: err } );
};
res.local( 'product', data );
next();
});
};
var transformProduct = function(req, res, next){
var product = res.locals().product;
transform( product, function(data){
res.local('product', data);
next();
});
};
var sendProduct = function(req, res, next){
var product = res.locals().product;
res.json(product);
};
app.get( '/product', getOne, transformProduct, sendProduct );
If you write middleware for your routes like this you'll end up with small building blocks you can easily reuse throughout your application.

Resources