In my express app, I have a utility function that controls the promise then
chain based on a specific condition. However, when I attempt to end the chain using a return
statement, Express throws an error stating that headers cannot be set after they are sent. Here is the code snippet:
function submit_reset_password_request(request, response) {
if (request.session.id) {
return response.json({ error: true, message: 'password reset cannot be requested during an active session' });
}
let { email } = request.body;
let user, reset_request;
if (email) {
email = email.toLowerCase().trim();
}
if (!email) {
return response.json({ error: true, message: 'input is required' });
}
models.Users.findOne({ where: { email } })
.then(user_result => {
if (!user_result) {
return response.json({ error: true, message: 'No account found with that email' });
}
user = user_result.dataValues;
return models.ResetPasswordRequests.findOne({ where: { user_email: user.email } })
})
.then(request_result => {
if (request_result) {
return response.json({ error: true, message: 'A password reset has already been requested for this email' });
}
return models.ResetPasswordRequests.create({ user_email: user.email })
})
.then(new_reset_request => {
reset_request = new_reset_request.dataValues;
// send reset request email
let host = request.get('host');
let link = host.endsWith('/') ? (host + 'search') : (host + '/search');
let email_subject = 'Epsity - Password reset requested';
let email_html = templateEngine.PasswordReset_EMAIL({ user, reset_request, link });
return sendgrid_manager.send_email(null, request.session.you.email, email_subject, email_html);
})
.then(email_result => {
return response.json({ success: true, message: 'A password reset request has been sent to the provided email!' });
})
.catch(error => {
console.log(error);
return response.json({ error, message: 'Could not submit reset password request...' });
});
}
Despite the if
statements intended to stop the chain and send a response, it continues executing regardless (although the response can still be seen on the client side). The cause of this behavior is unclear.
Below is the error message received:
Unhandled rejection Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:494:11)
at ServerResponse.setHeader (_http_outgoing.js:501:3)
at ServerResponse.header (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\express\lib\response.js:767:10)
at ServerResponse.send (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\express\lib\response.js:267:15)
at models.Users.findOne.then.then.then.then.catch.error (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\server\routers\main\methods\post.js:221:21)
at tryCatcher (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\bluebird\js\release\promise.js:512:31)
at Promise._settlePromise (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\bluebird\js\release\promise.js:569:18)
at Promise._settlePromise0 (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\bluebird\js\release\promise.js:614:10)
at Promise._settlePromises (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\bluebird\js\release\promise.js:690:18)
at _drainQueueStep (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\bluebird\js\release\async.js:138:12)
at _drainQueue (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\bluebluebirdird/js/release/async.js:131:9)
at Async._drainQueues (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\bluebird\js\release\async.js:147:5)
at Immediate.Async.drainQueues (C:\Users\Waite-Ryan-M\Desktop\_my-apps\rmw-epsity\node_modules\bluebird\js\release\async.js:17:14)
at runCallback (timers.js:789:20)
at tryOnImmediate (timers.js:751:5)
at processImmediate [as _immediateCallback] (timers.js:722:5)
I might consider implementing the async/await
syntax as a potential solution.