Reputation: 1992
Calling an async function in a pre save hook is returning me undefined
for the password. Am I fundamentally misunderstanding async
here? I've used it successfully in other areas of my app an it seems to be working fine...
userSchema.pre('save', function (next) {
let user = this
const saltRounds = 10;
const password = hashPassword(user)
user.password = password;
next();
})
async hashPassword(user) {
let newHash = await bcrypt.hash(password, saltRounds, function(err, hash) {
if (err) {
console.log(err)
}
return hash
});
return newHash
}
Upvotes: 4
Views: 6775
Reputation: 168
Mongoose hooks allow async functions in them. It worked for me. Note that the "next" callback parameter is not needed in async functions as the function executes synchronously.
Here is what a correct async/await version of the code posted in the question would be. Please note that the corrections are marked in bold:
userSchema.pre('save', async function () {
let user = this;
const saltRounds = 10;
const hashed_password = await hashPassword(user.password, saltRounds);
user.password = hashed_password;
}); // pre save hook ends here
async hashPassword(password, saltRounds) {
try {
let newHash = await bcrypt.hash(password, saltRounds);
} catch(err){
// error handling here
}
return newHash;
}
Upvotes: 3
Reputation: 2185
Just to clean things up a bit:
userSchema.pre('save', function(next) {
if (!this.isModified('password')) {
return next();
}
this.hashPassword(this.password)
.then((password) => {
this.password = password;
next();
});
});
userSchema.methods = {
hashPassword(password) {
return bcrypt.hash(password, 10);
},
}
let user = this
can be dropped when using an arrow function in then
.bcrypt.hash()
with no callback, it returns a promise.Upvotes: 0
Reputation: 22553
I think you'd need to handle the promise returned by hashPassword:
hashPassword(user)
.then(password => {user.password = password
next()}
)
I don't think you can turn userSchema.pre into an async function.
Upvotes: 4