Reputation: 2543
Below is my stylized code :
let the_function = (req, res, next) => {
Promise
.map(promises_params, (x) => {
return get_promise(x);
}, {concurrency: 20}
).then((values) => {
let reduceFunc = (acc, currV, currI) => {
if (something_bad) {
next(new Error("something bad happened");
return;
} else {
return acc;
}
};
let result = values.reduce(reduceFunc,[]);
res.send(result);
}).catch((err) => {
res.send(err);
});
};
The idea is that I am running a bunch of promises then reducing the values I get to a single object which I then send back to the user.
When something_bad
happens within the reduce function reduceFunc
, I would like to get a proper error sent back to the user. But in my current setup, the node.js server fails and has to reboot after I get :
_http_outgoing.js:494
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
and the user gets an error which is not the one I would like her to see.
How to make sure the error I want the user to see is output cleanly without killing the server in the meantime ?
Upvotes: 1
Views: 40
Reputation: 6063
The reason you are running into an error is because calling next
does not stop the reduce function from executing. The reduce function continues to run and eventually res.send(results)
is called. This becomes a problem because the next route handler is apparently also sending a response, but only one response can be sent for a request so you get an error.
The fact that you are not calling next
in your catch handler indicates that you don't really want to use next
. Since that is the case you can simply throw
the error so that execution of the reduce function is haulted and the catch handler is invoked.
let the_function = (req, res, next) => {
Promise
.map(promises_params, (x) => {
return get_promise(x);
}, {concurrency: 20}
).then((values) => {
let reduceFunc = (acc, currV, currI) => {
if (something_bad) {
throw new Error("something bad happened");
} else {
return acc;
}
};
let result = values.reduce(reduceFunc,[]);
res.send(result);
}).catch((err) => {
res.send(err);
});
};
Now a response is only sent once. It is sent if the reduce function completes without something_bad
happening, or when an error occurs, but never both.
Upvotes: 1