Reputation: 71
I am trying to query some documents from my MongoDB database, then add the documents to an array, and then send it to a rendered view. However, it seems that the line that I have to render the page is getting executed before the db query is completed. Below is the code:
router.get('/blog/:username/:postid', async function(req, res, next) {
var posts = [];
await collPosts.find( { $and : [{ postid : parseInt(req.params.postid) }, { username : req.params.username }] }, function(err, docs) {
docs.each(function(err, doc) {
if (doc) {
var renderedTitle = renderer.render(parser.parse(doc.title));
var renderedBody = renderer.render(parser.parse(doc.body));
var post = { postid : doc.postid, username : doc.username, created : doc.created, modified : doc.modified, title : renderedTitle, body : renderedBody };
posts.push(post);
console.log("0"); // EDIT
}
});
console.log("1"); // EDIT
});
console.log("2"); // EDIT
res.render('index', { title : 'Post Results', Posts : posts });
});
I am very new to using Express, so if someone could help me to get the query to execute, and then the page to render, it would be greatly appreciated. Currently, where I log the posts array to console, the posts array is empty (as it is executing before the query is completed). Thanks
EDIT: When using the async/await approach (and some debugging), the 2 is now being logged to console before the 1 as expected. However, the 0 is being logged to console after 1 and 2. Could someone help me to resolve this please? Thanks
Upvotes: 1
Views: 311
Reputation: 395
I have been coding a lot in express lately, and sometimes the issue when querying the database is that it returns a promise. You can either provide a callback or use ES6 async/await as shown below. Hope this helps!
router.get('/blog/:username/:postid', async function(req, res, next) {
var posts = [];
await collPosts.find( { $and : [{ postid : parseInt(req.params.postid) }, { username : req.params.username }] }, function(err, docs) {
docs.each(function(err, doc) {
if (doc) {
var renderedTitle = renderer.render(parser.parse(doc.title));
var renderedBody = renderer.render(parser.parse(doc.body));
var post = { postid : doc.postid, username : doc.username, created : doc.created, modified : doc.modified, title : renderedTitle, body : renderedBody };
posts.push(post);
}
});
});
console.log(posts);
res.render('index', { title : 'Post Results', Posts : posts });
});
Upvotes: 0
Reputation: 4488
This happens because I/O operations are asynchronous operations. You must wait for your db response and then send it back to client. You are sending res.render
outside find
callback, which results in sending response to client before your db returns something. Put your res.render
inside find
callback so you will be sure you will only send your response to client after db get your docs.
router.get('/blog/:username/:postid', function(req, res, next) {
var posts = [];
collPosts.find( { $and : [{ postid : parseInt(req.params.postid) }, { username : req.params.username }] }, function(err, docs) {
docs.each(function(err, doc) {
if (doc) {
var renderedTitle = renderer.render(parser.parse(doc.title));
var renderedBody = renderer.render(parser.parse(doc.body));
var post = { postid : doc.postid, username : doc.username, created : doc.created, modified : doc.modified, title : renderedTitle, body : renderedBody };
posts.push(post);
}
});
console.log(posts);
res.render('index', { title : 'Post Results', Posts : posts });
});
});
Upvotes: 3