NodeJs Can't set headers after they are sent

2020-03-31 06:14发布

问题:

In my project nodejs returns the following message:

Error: Can't set headers after they are sent. I have watched many question in this website but i stil cant find solution. Please help.!!!

Thats my code:

routes.js

var mongodb = require(__dirname+"/db.js");
var fs = require("fs");
var hbs = require("express3-handlebars");
var soap = require('soap');
var url = "http://infovalutar.ro/curs.asmx?wsdl";
var index = null;
module.exports = {
    home: function(req, res) {
        mongodb.db().collection("categories").find({id: req.params.category}).toArray(function(err, data) {

            for (j=0; j<data.length; j++) {
                for(i=0; i<data[j].categories.length; i++) {
                    var link_path = data[j].categories[i].categories;
                    link_path.type = { data: req.params.categorie };
                    res.render("home", {
                        location: data[j].id,
                        title: data[j].page_title,
                        name: data[j].name,
                        description: data[j].page_description,
                        mens_link: "/mens",
                        womens_link: "/womens",
                        data_id: data[j].id,
                        type: req.params.categoriy,
                        cat: data[j].categories,
                        categories: data[j].categories[i].categories
                    });
                }
            }   
        });
    },
    product_list: function(req, res) {
        mongodb.db().collection("products").find({primary_category_id: req.params.sub_category}).toArray(function(err, data) {

            for (s=0; s<data.length; s++) {
                for (v=0; v<data[s].image_groups.length; v++) {

                    res.render("product_list", {
                        products: data,
                        mens_link: "/mens",
                        womens_link: "/womens",
                        main: req.params.category,
                        sub: req.params.sub_category,
                        id: req.params.id,

                    });
                }
            }
        });
    },
    single_product: function(req, res) {
        mongodb.db().collection("products").find({id: req.params.id}).toArray(function(err, data) {
        for (s=0; s<data.length; s++) {
            for (v=0; v<data[s].image_groups.length; v++) {

                res.render("product", {
                    single_product: data,
                    mens_link: "/mens",
                    womens_link: "/womens",
                    main: req.params.category,
                    sub: req.params.sub_category,
                    id: req.params.id,
                });
            }
        }

        });
    }
};

回答1:

Unfortunately it does not work that way. You are calling the function render() that makes the rendering engine send the specified layout's data and close the connection. That is exactly why you are getting the headers already sent error.

The function res.render() should only be called once per request.

Create an array var response=[] and change your loops like this:

        var response=[];
        for (j=0; j<data.length; j++) {
            for(i=0; i<data[j].categories.length; i++) {
                var link_path = data[j].categories[i].categories;
                link_path.type = { data: req.params.categorie };
                response.push({
                    location: data[j].id,
                    title: data[j].page_title,
                    name: data[j].name,
                    description: data[j].page_description,
                    mens_link: "/mens",
                    womens_link: "/womens",
                    data_id: data[j].id,
                    type: req.params.categoriy,
                    cat: data[j].categories,
                    categories: data[j].categories[i].categories
                });
            }
        }   
        res.render('home', response);

and in your for loops, push each of your to-be-rendered items into that array.

Note that you will get an array of objects in your response in your home layout.