为什么链接承诺不起作用?

时间:2018-02-05 18:33:29

标签: javascript node.js es6-promise

我不明白为什么这个代码块会抛出错误:

  

无法读取未定义的属性'然后'

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

成功记录哈希值

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

因为bcrypt.hash返回 - Promise<string>这两个代码块不应该起作用(日志哈希)吗?

谢谢!

4 个答案:

答案 0 :(得分:4)

genSalt函数返回一个promise(编辑:当省略回调时它会执行)。相反,它需要一个回调,无论你从该回调函数返回什么,都与genSalt的返回完全分开。也就是说,无论你的回调函数返回什么,genSalt都会返回undefined。

所以为了让它工作,你可以将genSalt函数包装成一个这样的承诺:

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

然后你可以像这样使用它:

genSaltPromise(10).then(salt => {
    return bcrypt.hash(password, salt);
}).then(hash => {
    console.log(hash);
});
编辑:正如@Bergi所指出的,genSalt确实在没有指定回调时返回一个承诺。所以上面的内容可以简化为:

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

答案 1 :(得分:4)

来自the docs

  

接受回调的异步方法,如果Promise支持可用,则在未指定回调时返回Promise。

所以只需省略回调并使用then 代替

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

答案 2 :(得分:1)

第一个代码段失败,因为在.then(..)的返回值中调用了genSalt(..);基于错误消息,我会说该方法不会返回任何内容。

第二个代码段有效,因为您正在调用bcrypt,这是一个承诺。

答案 3 :(得分:1)

Promise由回调函数返回,而不是bcrypt.genSalt。因此,如果使用回调函数进行链接,then将起作用,而不是bcrypt.genSalt。如果要将thenbcrypt.genSalt一起使用,则需要将其包含在承诺中。例如: -

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