Eugene Goldberg Eugene Goldberg - 1 year ago 54
Javascript Question

how to properly send the response code from Node.js API

I have a simple node-based API, which needs to parse some JSON, save some data into Postgres, and then, send the appropriate response code (like http 201).
My code looks like this:


.post(function(req, res) {
Customers = req.body;
var numberOfCustomers = Customers.length;
for(var i = 0; i < Customers.length; i++){
Customer = Customers[i];
console.log(Customer.Name + " " + Customer.Address);
var date = moment(new Date()).unix();

'INSERT into customer (name, address, date_modified) VALUES($1, $2, $3) RETURNING id',
[Customer.Name, Customer.Address, date],
function(err, result) {
if (err) {
status = 1;
} else {
console.log('row inserted with id: ' + result.rows[0].id);
if(numberOfCustomers === i) {
res.status(201).send({ message: "created" });

I'm getting this error:


throw new Error('Can\'t set headers after they are sent.');

Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)

I need to account for the fact, that I'm performing my Postgres insert multiple times within a loop, so I can not send my response headers after just the first insert is done.

What is the most appropriate place within my 'POST' handler to put my
res.status(201).send({ message: "created" });


Answer Source

Architectural decisions aside (for example, you might want a separate module that acts as an HTTP adapter to handle logic for sending response codes as opposed to doing it inside of your route controller), you can use promises to wait for all the inserts to finish and then send a single response code. For example, something like this:

var Promise = require('bluebird');
var query = Promise.promisify(client.query);

.post(function(req, res) {
   // all your logic, and then

   return Promise.all( {
     return query(sql, [Customer.Name, Customer.Address, date]);
   .then(function() {
     res.status(201).send({ message: 'Created' });

Check out the the bluebird docs for the API used in this example.

I'm unfamiliar with Postgres's API, but the concept should be similar: you need to wait for all the requests to your DB to be resolved first.