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?
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 .
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.
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.
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.
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
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With