I am aware that it is related to; setting the header a second time doesn't work, but my app is crashing after sending the first response without even sending another request.
When the app crashes the console indicates to check the catch block of the code.
My major concern is why is the execution entering the catch block when there is no error in the execution, because I only want to check if the user exists, and from what I understand the result should be same irrespective of the number of times we check. If I try to add a user that already exists this is correctly working and I am getting the output:
if (user.rows.length !== 0) {
res.status(400).json("User already exists");
}
then why is my catch block being called after sending the json? I have tried changing the response status code and changing the to res.status(401).send("User already exists");
also gives the same error, but once I only change the status and send no message the server works fine with res.status(401)
, why is my catch block being invoked after sending the response with json/send??
What is a better approach I can incorporate here?
This is the code:
try {
// extract data from request body
const { user_name, user_email, user_password } = req.body;
// check if user already exists
const user = await pool.query("SELECT * FROM users WHERE user_email = $1", [user_email]);
// console.log(typeof user); returns object
// console.log(user.rows);
if (user.rows.length !== 0) {
res.status(400).json("User already exists");
}
// bcrypt the user password
const saltRound = 10; // Try randomising the salt rounds
const salt = await bcrypt.genSalt(saltRound);
const bcryptPassword = await bcrypt.hash(user_password, salt); // encrypted password
// insert user into database
const newUser = await pool.query("Insert INTO users (user_name, user_email, user_password) VALUES ($1, $2, $3) RETURNING *", [user_name, user_email, bcryptPassword]);
res.json(newUser.rows[0]);
} catch (error) {
console.error(error.message);
res.status(500).send("Server Error");
}
Error in console:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
CodePudding user response:
You are getting this error because you didn't check the else block. after checking the if statement it goes down and try to execute the rest of the code. your catch block isn't executed cause if it is you'll get 500. Try executing the code like below-
if (user.rows.length !== 0) {
res.status(400).json("User already exists");
}else{
// bcrypt the user password
const saltRound = 10; // Try randomising the salt rounds
const salt = await bcrypt.genSalt(saltRound);
const bcryptPassword = await bcrypt.hash(user_password, salt); // encrypted password
// insert user into database
const newUser = await pool.query("Insert INTO users (user_name, user_email, user_password) VALUES ($1, $2, $3) RETURNING *", [user_name, user_email, bcryptPassword]);
res.json(newUser.rows[0]);
}
You can't execute both responses at once. Hope this will help you handle your problem.
CodePudding user response:
As per your code you are handling the if
block with wrong approach. In NodeJs as it is async in nature, It will never terminated as you expected. add return in the if
block.
if (user.rows.length !== 0) {
return res.status(400).json("User already exists");
}
It will return the response and break the execution of further code. As per your code it is executing the new user creation code and try to create the new user which is already present where the sql throws the error and it goes to the catch block. And agin try to send the new error response which gives you the ERR_HTTP_HEADERS_SEND
.
As per the best practices always handle the error cases 1st so it will not create the if-else
ladder.