Async function works with a callback does not work with await

Viewed 28

I am trying to integrate into my code an async library function. It works fine as:

client.checkPermission(checkPermissionRequest, (err, response) => {
  if (err || response?.permissionship !== HAS_PERMISSION) {
    const e = err || new Error('You do not have access to event:', id);
    res.code(404).send({ error: e });
  }
});

I want to rewrite it in an "await form" and this does not work. I have been trying:

const response = await client.checkPermission(checkPermissionRequest);

When I run the await code, it fails with: Error: Incorrect arguments passed.

Why could this be happening and how could I fix this?

2 Answers

await doesn't magically make a callback-based API return a promise.

You can however, wrap the call in a promise:

const response = await new Promise((resolve, reject) => {
    client.checkPermission(checkPermissionRequest, (err, response) => {
        if (err) return reject(err);

        return resolve(response);
    });
});

This is called "promisification". If you're a little confused as to how resolve and reject work, maybe the examples in MDN could help with that.

In Node environments you can use the node utility util.promisify to convert the calling conventions of a node style function taking an (error, value) callback as their last argument, into a function that returns a promise without taking a callback argument:

  const util = require('node:util');  //   **OR**
  import {promisify} from 'node:util';

  client.checkPermission = util.promisify( client.checkPermission)

And then call with

  const response = await client.checkPermission(checkPermissionRequest);

Core module imports

 import {promisify} from 'node:util';

imports the promisify utility in a script module. From the docs

Core modules provide named exports of their public API. A default export is also provided which is the value of the CommonJS exports

Related