zzzz
zzzz

Reputation: 161

why chaining the promise doesn't work?

I don't understand why this code block throws the error :

Cannot read property 'then' of undefined

bcrypt.genSalt(10,(err, salt) =>{
    if(err){
        console.log(err);
    }
    return bcrypt.hash(password,salt); 
}).then((hash)=>console.log(hash));

when this successfully logs the hash

bcrypt.genSalt(10,(err, salt) =>{
    if(err){
        console.log(err);
    }
    bcrypt.hash(password,salt).then((hash) => console.log(hash));
});

since bcrypt.hash returns - Promise<string> shouldn't both these code blocks supposed to work(log hash) ?

thanks !

Upvotes: 3

Views: 244

Answers (4)

CRice
CRice

Reputation: 32176

The genSalt function does not return a promise (EDIT: It does when the callback is omitted). Instead it takes a callback, and whatever you return from that callback function is completely separate from the return of genSalt. That is to say, genSalt returns undefined no matter what your callback function returns.

So in order to get this to work, you can wrap the genSalt function into a promise like so:

function genSaltPromise(num) {
    return new Promise((resolve, reject) => {
        bcrypt.genSalt(num, (err, salt) => {
            if (err) return reject(err);
            resolve(salt);
        })
    })
}

Then you could use it like so:

genSaltPromise(10).then(salt => {
    return bcrypt.hash(password, salt);
}).then(hash => {
    console.log(hash);
});

EDIT: As pointed out by @Bergi, the genSalt does return a promise when no callback is specified. So the above could be simplified to just:

bcrypt.genSalt(10).then(salt => {
    return bcrypt.hash(password, salt);
}).then(hash => {
    console.log(hash);
});

Upvotes: 4

Bergi
Bergi

Reputation: 664528

From the docs:

Async methods that accept a callback, return a Promise when callback is not specified if Promise support is available.

So just omit the callback and use then instead:

bcrypt.genSalt(10).then(salt => {
    return bcrypt.hash(password,salt); 
}).then(hash => {
    console.log(hash);
}, err => {
    console.log(err);
});

Upvotes: 4

Akash
Akash

Reputation: 4553

The Promise is returned by the callback function, not bcrypt.genSalt. So, then will work if chained with the callback function, not bcrypt.genSalt. If you want to use then with bcrypt.genSalt, you need to wrap it in a promise. e.g :-

new Promise((resolve, reject) => {
  bcrypt.genSalt(10,(err, salt) =>{
    if(err){
        console.log(err);
    }
     resolve(bcrypt.hash(password,salt)); 
  })
}).then((hash)=>console.log(hash));

Upvotes: 1

Babak Naffas
Babak Naffas

Reputation: 12561

The first snippet fails because .then(..) is being called in the return value for genSalt(..); based on the error message, I would say that the method does not return anything.

The second snippet works because you are calling is on bcrypt, which is a promise.

Upvotes: 1

Related Questions