Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node callback to promise with async/await

I'm trying to write a simple function that converts node-style callback functions to promises, so I can use them with async/await.

Current code:

function toPromise(ctx, func, ...args) {
  let newPromise;

  args.push((err, res) => {
    newPromise = new Promise((resolve, reject)=> {
       if(err) reject(err);
       else{
        resolve(res) 
      };
     });
    });

   func.apply(ctx, args);

   return newPromise;
}

example usage:

const match = await toPromise(user, user.comparePassword, password);
//trying to avoid the following:
user.comparePassword(password, (err, res) => {
     ... });

This probably doesn't make any sense with some great libraries out there, but I'm just trying to code this as an exercise.

Problem is of course match evaluates to undefined, and apparently the promise gets resolved after the await syntax line.

Any idea how I can resolve this issue?

like image 926
Seneca Avatar asked Nov 02 '15 11:11

Seneca


People also ask

Does async await work with callbacks?

The await keyword is used in an async function to ensure that all promises returned in the async function are synchronized, ie. they wait for each other. Await eliminates the use of callbacks in .

Can you use async await with promises?

async and await Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

What is callback promise async await?

Async/Await is used to work with promises in asynchronous functions. It is basically syntactic sugar for promises. It is just a wrapper to restyle code and make promises easier to read and use. It makes asynchronous code look more like synchronous/procedural code, which is easier to understand.

How do I change my callback to promise?

If the callback function returns non-error output, we resolve the Promise with the output. Let's start by converting a callback to a promise for a function that accepts a fixed number of parameters: const fs = require('fs'); const readFile = (fileName, encoding) => { return new Promise((resolve, reject) => { fs.


2 Answers

Since node v8.0.0 they added util.promisify.

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);
stat('.').then((stats) => {
  // Do something with `stats`
}).catch((error) => {
  // Handle the error.
});

Ref: https://nodejs.org/api/util.html#util_util_promisify_original

like image 132
aegyed Avatar answered Oct 17 '22 15:10

aegyed


Your problem is that you are constructing the newPromise inside of the asynchronous callback. So you've still got undefined when you return it. Instead, you will need to call the Promise constructor immediately, and only put the resolve/reject in the asynchronous callback:

function toPromise(ctx, func, ...args) {
    return new Promise((resolve, reject) => {
        args.push((err, res) => {
            if (err) reject(err);
            else resolve(res);
        });
        func.apply(ctx, args);
    });
}

See also How do I convert an existing callback API to promises?

like image 44
Bergi Avatar answered Oct 17 '22 15:10

Bergi