简体   繁体   中英

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 !

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);
});

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);
});

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.

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. eg :-

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM