I’m having an issue that I don’t understand with my Express + MongoDB + bcrypt code.
I know how to solve it, but I’d like to understand why it’s happening.
const storeNewUserIntoDatabase = async (user) => {
const newUser = { ...user, access: true, admin: false };
await bcrypt.hash(user.pass, saltRounds, async (error, hashedPass) => {
if (error) throw new Error(error);
const result = await Users.insert({ ...newUser, pass: hashedPass });
if (!result) return '';
return result;
});
}
// Route -------------------------------------------------
auth.post('/signup', async (req, res) => {
try {
let response;
const {
name, email, pass, confirmPass,
} = req.body;
if (pass !== confirmPass) {
response = {
ok: false,
message: 'The passwords do not match',
};
}
// This line below is the one that's causing problems...
const successfullNewUserId = await storeNewUserIntoDatabase({ name, email, pass });
if (!successfullNewUserId) {
response = {
ok: false,
message: 'Operation failed, no user was added to the database',
};
} else {
response = {
ok: true,
message: 'User created successfully',
user_id: successfullNewUserId,
};
}
res.send(response);
} catch (err) {
throw new Error(err);
}
});
I thought that the ‘await’ keyword would pause the execution of the code until ‘storeNewUserIntoDatabase’ returned it’s value, but the ‘if’ statements below execute with ‘successfullNewUserId’ being ‘undefined’, even when the user was actually successfully added to the database.
I can modify the function ‘storeNewUserIntoDatabase’ to execute a callback, and that would fix it, but I’d like to understand WHY the await is not working in this case like it usually does.
Good observation. I changed my code to return something from that function, but it didn’t make any difference for the problem I was having.
Here is what the code looks like now:
const signInUser = async (user) => {
const newUser = { ...user, access: true, admin: false };
const resultFromHashing = await bcrypt.hash(user.pass, saltRounds, async (error, hashedPass) => {
if (error) throw new Error(error);
const result = await Users.insert({ ...newUser, pass: hashedPass });
console.log(`Result INSIDE the bycrpt callback: ${result} // This happened in second: ${new Date().getUTCSeconds()}`);
return result;
});
console.log(`Result OUTSIDE the bycrpt callback: ${resultFromHashing} // This happened in second: ${new Date().getUTCSeconds()}`);
if (!resultFromHashing) return '';
return resultFromHashing;
};
And this is what the console looks like with the logs (notice how the result from outside the callback is still being called first, even though I’m awaiting the callback):
Result OUTSIDE the bycrpt callback: undefined // This happened in second: 5
Result INSIDE the bycrpt callback: 5fc7f11ac363a4b06f7a15b0 // This happened in second: 6
It’s quite a mystery to me. I think that if I’m able to understand this, it will deepen my understanding of how async/await and promises in general work, so I’m excited!