Reputation: 1992
Following on from this question.
I feel like I'm almost there, but my incomplete understanding of async is preventing me from solving this. I'm basically trying to just hash a password using bcrypt and have decided to seperate out the hashPassword function so that I can potentially use it in other parts of the app.
hashedPassword
keeps returning undefined though...
userSchema.pre('save', async function (next) {
let user = this
const password = user.password;
const hashedPassword = await hashPassword(user);
user.password = hashedPassword
next()
})
async function hashPassword (user) {
const password = user.password
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(password, saltRounds, function(err, hash) {
if (err) {
return err;
}
return hash
});
return hashedPassword
}
Upvotes: 34
Views: 57688
Reputation: 580
Had same issue... solved by assigning the Boolean value from a function:
compareHash = (password, hashedPassword) => {
if (!password || !hashedPassword) {
return Promise.resolve(false);
}
return bcrypt.compare(password, hashedPassword);
};
Here the 2 arguments will not be undefined, which is the cause of issue. And calling the function:
let hashCompare = this.compareHash(model.password, entity.password);
Upvotes: 0
Reputation: 317
const hashedPassword = (password, salt) => {
return new Promise((resolve, reject) => {
bcrpyt.hash(password, salt, (err, hash) => {
if (err) reject();
resolve(hash);
});
});
};
hashedPassword('password', 10).then((passwordHash) => {
console.log(passwordHash);
});
Upvotes: 0
Reputation: 4553
await
dosent wait forbcrypt.hash
becausebcrypt.hash
does not return a promise. Use the following method, which wrapsbcrypt
in a promise in order to useawait
.
async function hashPassword (user) {
const password = user.password
const saltRounds = 10;
const hashedPassword = await new Promise((resolve, reject) => {
bcrypt.hash(password, saltRounds, function(err, hash) {
if (err) reject(err)
resolve(hash)
});
})
return hashedPassword
}
Update:-
The library has added code to return a promise which will make the use of
async/await
possible, which was not available earlier. the new way of usage would be as follows.
const hashedPassword = await bcrypt.hash(password, saltRounds)
Upvotes: 100
Reputation: 3713
You need to look here in the documentation.
Async methods that accept a callback, return a Promise when callback is not specified if Promise support is available.
So, if your function call takes in a callback then you can't use await
on it since this function signature doesn't return a Promise
. In order to use await
you need to remove the callback function. You can also wrap it in a Promise
and await
on it but that's a bit overkill since the library already provides a mechanism to do so.
Code refactor:
try {
// I removed the callbackFn argument
const hashedPassword = await bcrypt.hash(password, saltRounds)
} catch (e) {
console.log(e)
}
Upvotes: 2
Reputation: 455
use The method bcrypt.hashSync(), It is Synchronous out of the box.
const hashedPassword = bcrypt.hashSync(password,saltRounds);
Upvotes: 6
Reputation: 251
By default, bcrypt.hash(password,10)
will return as promise. please check here
Example: Run the code,
var bcrypt= require('bcrypt');
let password = "12345";
var hashPassword = async function(){
console.log(bcrypt.hash(password,10));
var hashPwd = await bcrypt.hash(password,10);
console.log(hashPwd);
}
hashPassword();
Output:
Promise { <pending> }
$2b$10$8Y5Oj329TeEh8weYpJA6EOE39AA/BXVFOEUn1YOFC.sf1chUi4H8i
When you use await
inside the async function, it will wait untill it get resolved from the promise.
Upvotes: 25
Reputation: 569
Hashing bcrypt asynchronously should be like this
bcrypt.hash(password, saltRounds, function(err, hash) {
if (err) {
throw err;
}
// Do whatever you like with the hash
});
If you are confused with sync and async. You need to read more about them. There are a lot of good articles out there.
Upvotes: 3