I am working with Node.js, Express.js, and a MySQL database. Within the database I have posts that I would like to display using Pug.js view engine. I got it to work by connecting to the database and rendering the home route correctly but I am apparently making a second callback because I get the Error:
Can't set headers after they are sent.
I am unsure of how to fix this without breaking it further because it actually renders as expected now. Here is what I am working with:
app.js:
// Home Route
app.get('/', function(req, res){
//get posts from database to show on news section.
var postList = [];
db.query('SELECT * from articles', function(err, rows) {
if(err) throw err;
for (var i = 0; i < rows.length; i++) {
//missing the img fields
var post = {
'id':rows[i].id,
'title':rows[i].title,
}
//Add the newly created post object to the postList array
postList.push(post);
//THE ERROR IS PROBABLY BECAUSE OF THIS \/
res.render('index', {
title:'mySite',
page: 'News',
postList: postList});
}
});
});
here is the index.pug:
extends layout
block content
table
for post in postList
tr
td
h3 #{post.title}
td
p #{post.id}
Once again it renders fine but the terminal is throwing the error at me and i would prefer to fix it if possible. I have tried to pull the res.render for the index out of the query like this:
// Home Route
app.get('/', function(req, res){
//get posts from database to show on news section.
var postList = [];
db.query('SELECT * from articles', function(err, rows) {
if(err) throw err;
for (var i = 0; i < rows.length; i++) {
//missing the img fields
var post = {
'id':rows[i].id,
'title':rows[i].title,
}
//Add the newly created post object to the postList array
postList.push(post);
}
});
//THIS FIXES THE ERROR \/
res.render('index', {
title:'mySite',
page: 'News',
postList: postList});
//THIS NO LONGER RENDERS THE postList ARRAY
});
Any help with this would be appreciated. Thanks.
You almost made it right, man! but the render
should be inside db.query
such as
//get posts from database to show on news section.
var postList = [];
db.query('SELECT * from articles', function (err, rows) {
if (err) throw err;
for (var i = 0; i < rows.length; i++) {
//missing the img fields
var post = {
'id': rows[i].id,
'title': rows[i].title,
}
//Add the newly created post object to the postList array
postList.push(post);
} // end for loop
res.render('index', {
title: 'mySite',
page: 'News',
postList: postList
});
});
The explanation is db.query
is callback function, if you put res.render
outside it, javascript engine will execute it first so you will get nothing in your postList
. So, you must wait until db.query
finish and populate your postList
then render it.
Why you got Can't set headers after they are sent because you execute res.render
multiple times (you put it inside the loop). It must be executed just once.
Hope it helps.