In this guide you will learn how to use Node’s util.promisify
to promisify your own functions. This utility function was included in NodeJS version 8. If you plan to follow along with this guide you’ll need to install the latest version. As an added bonus I also show you how to use promisify
with await
and async
.
util.promisify
converts a regular function into an async function, i.e. a function that returns a promiseutil.promisify
must follow the NodeJS callback style. The function must pass a callback as the last parameter, and the callback must be the take the following parameters in the following order: (err, value) => { /* … */ }
await
and async
to help avoid messy promise chains and introduce a cleaner, saner, way to do asynchronous programming.The official node documentation says:
Takes a function following the common Node.js callback style, i.e. taking a
(err, value) => ...
callback as the last argument, and returns a version that returns promises.
And …
promisify(original)
assumes thatoriginal
is a function taking a callback as its final argument in all cases, and the returned function will result in undefined behaviour if it does not.
So basically it’s a utility function that takes a regular function and converts it to a function that returns a promise/s.
The function passed to util.promisify
has to follow a couple of conventions:
promisify
must be a callback.Here is an example of a valid function:
Note: For anyone unfamiliar with the syntax I’m using ES6. I also use the Airbnb style guide.
To demonstrate how util.promisify
works lets start by creating a regular function that performs a task over a long period of time. We will then convert this function to a promise.
Below I have a function called wait
. Its purpose is to make you wait for an unknown period of time:
For demonstration purposes I’ve wrote the function to wait for an unknown period of time. It does this by using setInterval
to call an anonymous function every x
number of seconds and compares the number to a set of values to decide whether to continue waiting, or to stop:
0.95
the function will stop running and the callback function will be called.0.01
an error will be passed to the callback function.util.promisify
expects a function that conforms to NodeJS’s callback style. To learn more about Node’s callback style read this article: The Node.js Way — Understanding Error-First Callbacks
In the wait
function you will notice I used the callback is used in 2 different ways. When the random number was greater than 0.95
this is considered a success and the wait is over. Thus we can call the callback like so:
callback(null, ‘Congratulations, you have finished waiting.’);
Here I passed null
to the first parameter. No error occurred. Nothing to report. Using the second parameter I pass some data that is made available in the callback, or promise chain.
When the wait
function failed (in this case when the random number is below 0.01
) an error message is passed to the first parameter. The second parameter is set to null
.
callback(‘Could not wait any longer!’, null);
This follows Node’s callback style.
The function is called like so:
the function expects 2 parameters. The first is the number of milliseconds to wait before setInterval
calls the callback function. The second parameter is a callback.
Notice how I’m checking for an error: if (err) throw new Error(err)
… if err
is null
the callback continues. Otherwise an exception is thrown.
Running the above code produces the following output on success:
… and the following output on error:
We confirm the function does as expected. Next we will turn it into a promise.
Here’s where the magic happens.
Now we have an ordinary function I can demonstrate how to turn into a function that returns a promise. This is surprisingly easy …
That’s it. In 2 lines of code I converted the function to a promise. Line 7 to 9 show how to use the new promise. You will agree it’s much cleaner and easier to read.
Wait, we’re not finished yet. I’ve got some more juicy goodness to share with you. Node 8 also comes with async
and await
support. How freakin’ cool!
Instead of using promise chaining (which can get very messy very quickly) you can write your code in a normal procedural style like so:
No more promise chains :)
For more information on async/await I highly recommend the following article: https://blog.risingstack.com/mastering-async-await-in-nodejs/
P.S. If you’re on Twitter give me a follow. I often write articles on software development, and security: https://twitter.com/JamesJefferyUK