I'm writing a function to generate a random key using crypto.randomBytes, which takes a callback. I'd prefer to use async await so I'm trying to use util.promisify to wraprandom bytes like this:
const crypto = require('crypto');
const util = require('util');
const randBytes = util.promisify(crypto.randomBytes);
async function genRandKey() {
bytes = await randBytes(48).catch((err) => {
console.log(err);
});
return bytes.toString('hex');
}
let result = genRandKey();
console.log('key: ', result);
But this prints key: Promise { <pending> }
instead of printing the resolved value. What am I doing wrong here?
All async
functions return a promise., So your genRandKey()
function returns a promise too. You have to use await
or .then()
on the result from genRandKey()
. Just because you converted to a promise and used await
does not mean you can directly return the value from the function. That's not what is happening in an async
function. The return
value in an async
function just becomes the resolved value of the promise that the function returns. While, the code looks like you are returning the value directly, that's not what is actually happening.
In Javascript/node.js, there is NO way to take an asynchronously retrieved value and return it directly from a function. It has to be communicated back via a promise or a callback or an event. There is no way around it.
Now, in this specific case, there IS a synchronous version of crypto.randomBytes()
and you could use that instead. The asynchronous version exists for a reason because crypto.randomBytes()
takes a little while to run and if you use the synchronous version, it will block the event loop while it is running. Depending upon exactly what you are doing, this may or may not be a problem . The asynchronous version of crypto.randomBytes()
runs the actual crypto operations in a separate thread (using the libuv thread pool) and returns the value asynchronously so it doesn't block the event loop.