Node.js中用async/await调用pbkdf2报错:No callback provided to pbkdf2
嘿,我来帮你理清这个问题~
为什么异步版本的pbkdf2用await会报错?
你遇到的"Error: No callback provided to pbkdf2"错误,核心原因是Node.js 8.10.0里的crypto.pbkdf2只有回调式API,并没有原生支持Promise。
你能成功用await调用randomBytes,是因为从Node.js 8.x开始,randomBytes已经做了兼容:当你不传回调函数时,它会自动返回一个Promise;但pbkdf2在这个版本还没实现这个特性,它强制要求你传入回调函数,否则就会抛出错误。
怎么在async函数里异步使用pbkdf2?
最简单的方法是用Node.js内置的util.promisify工具,把回调风格的pbkdf2转换成Promise风格的函数,这样就能用await调用了。给你写个完整的示例:
const crypto = require('crypto'); const util = require('util'); // 把回调式的pbkdf2转换为Promise版本 const pbkdf2Async = util.promisify(crypto.pbkdf2); async function hashPassword(password) { try { // 生成随机盐(这里可以正常用await,因为randomBytes支持Promise) const salt = await crypto.randomBytes(16); // 用await调用转换后的pbkdf2 const hashBuffer = await pbkdf2Async( password, salt, 100000, // 迭代次数,建议设高一点保证安全性 64, // 哈希结果的字节长度 'sha512' // 哈希算法 ); // 把Buffer转成十六进制字符串,方便存储 return { salt: salt.toString('hex'), hash: hashBuffer.toString('hex') }; } catch (error) { console.error('生成密码哈希失败:', error); throw error; // 把错误抛出去让上层处理 } }
能不能在同步函数pbkdf2Sync上使用await?
可以,但完全没必要。await的作用是等待一个Promise的状态变更,如果后面跟的不是Promise,它会把这个值包装成一个已完成状态的Promise,然后立即返回结果。
比如await crypto.pbkdf2Sync(...)不会报错,但pbkdf2Sync本身是阻塞事件循环的同步操作,await并不会让它变成异步,反而多了一层无意义的Promise包装,不如直接调用crypto.pbkdf2Sync(...)来得直接。
额外补充
如果你的项目能升级Node.js版本到10.x及以上,crypto.pbkdf2就已经原生支持Promise风格调用了(不传回调时自动返回Promise),这时就不需要用util.promisify转换了,直接await crypto.pbkdf2(...)就行。
内容的提问来源于stack exchange,提问作者Danial Khansari

