Deeps HIT Deeps HIT - 4 months ago 8
Node.js Question

Error: Can't set headers after they are sent. Express.js

Im kinda new at node and stack for a long time with this error. Please help me sovle my problem.
Here is my code:

app.get('/', function(req , res){
request(url, function(err, response, html){
if (!err && response.statusCode == 200){
var page = cheerio.load(html);
page('.search-result-description').each(function(){
var data = [];
var name = page(this).find('.search-result-item__head');
var company = page(this).find('.search-result-item__company');
var description = page(this).find('.search-result-item__snippet');
var requirements = page(this).find('.search-result-item__snippet');
var salary = page(this).find('.b-vacancy-list-salary');

data.push({
vac_name: name.eq(0).text(),
vac_description: description.eq(0).text(),
vac_requirements: requirements.eq(0).text(),
var_company: company.eq(0).text(),
vac_salary : salary.eq(0).text()
});
data = JSON.stringify(data, null, 4);
res.render('main.ejs', {data: data});
});
}
});
});

Answer

Methods that send the http response like res.render() can only be called once per request (there's only one response per request). When you call them more than once, you get the error message about headers already being sent.

Assuming your page() function is synchronous, you just need to move a couple statements after the end of the loop instead of inside the loop and move your declaration of the data variable outside the loop too so you can accumulate data with the loop:

app.get('/', function(req, res) {
    request(url, function(err, response, html) {
        if (!err && response.statusCode == 200) {
            var page = cheerio.load(html);
            var data = [];
            page('.search-result-description').each(function() {
                var name = page(this).find('.search-result-item__head');
                var company = page(this).find('.search-result-item__company');
                var description = page(this).find('.search-result-item__snippet');
                var requirements = page(this).find('.search-result-item__snippet');
                var salary = page(this).find('.b-vacancy-list-salary');

                data.push({
                    vac_name: name.eq(0).text(),
                    vac_description: description.eq(0).text(),
                    vac_requirements: requirements.eq(0).text(),
                    var_company: company.eq(0).text(),
                    vac_salary: salary.eq(0).text()
                });
            });
            res.render('main.ejs', {
               data: JSON.stringify(data, null, 4);
            });
        }
    });
});

You also should have some error handling if the request() operation returns an error. As it stands how, you just never respond to the request.

Comments