How to use await with promisify for crypto.randomBytes?

匆匆过客 提交于 2021-02-11 17:01:06

问题


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?


回答1:


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.




回答2:


The async function genRandKey() is being called synchronously, so it will return a Promise. You can use the .then() function to write to the console after the function has completed. You need to change the following code:

let result = genRandKey();
console.log('key: ', result);

to

genRandKey().then((result) => {
    console.log('key: ', result);
});

However, this will cause the function to be called asynchronously while the rest of your code runs. A solution could be to wrap your whole program in a self-executing async function and use the await keyword:

(async () => {
    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 = await genRandKey();
    console.log('key: ', result);
})();

Alternatively, you could just put the rest of the code in the .then() function:

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

genRandKey().then((result) => {
    console.log('key: ', result);

    ...rest of code...
});


来源:https://stackoverflow.com/questions/61528374/how-to-use-await-with-promisify-for-crypto-randombytes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!