# Node.js 8: util.promisify() 💡

By Zubair Ahmed · Published 2017-09-29
Source: https://www.grizzlybit.dev/blog/nodejs-util-promisify

Node.js 8 has a new utility function: util.promisify(). It converts a callback-based function to a Promise-based one. Since we are on this topic I would like to highlight one of the most straight forward explanation for promises that I have come across by [Jecelyn Yeen](https://scotch.io/@jecelyn)

> Imagine you are a kid. Your mom promises you that she'll get you a new phone next week. You don't know if you will get that phone until next week. Your mom can either really buy you a brand new phone, or stand you up and withhold the phone if she is not happy :(. <cite>Jecelyn Yeen</cite>

## So now, what does util.promisify do?

In a very abstract way, it does the following:

> 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 that original 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.

If you haven't got it already, it basically, a utility function that takes a regular function and converts it to a function that returns a `promise`.

It has the following syntax:

```js
const wait = (delay, callback) => {
  /* … */
};
```

1. The last parameter of the function passed to `promisify` must be a callback
2. The callback must follow Node's callback style

But at the same time you can couple this with async to avoid the callback hell effectively.

![Callback Hell](https://www.grizzlybit.dev/blog/nodejs-util-promisify/callback.jpg)

## Lets see it in action

```js
const { promisify } = require('util');

const fs = require('fs');
const readFileAsync = promisify(fs.readFile); // (A)

//some path
const filePath = process.argv[2];

readFileAsync(filePath, { encoding: 'utf8' })
  .then((text) => {
    console.log('CONTENT:', text);
  })
  .catch((err) => {
    console.log('ERROR:', err);
  });
```

us implement the same using `asnyc` function:

```js
const { promisify } = require('util');

const fs = require('fs');
const readFileAsync = promisify(fs.readFile);

const filePath = process.argv[2];

async function main() {
  try {
    const text = await readFileAsync(filePath, { encoding: 'utf8' });
    console.log('CONTENT:', text);
  } catch (err) {
    console.log('ERROR:', err);
  }
}
main();
```

There are a few changes and qwirks you should adher to before implementing promisify, they are:

### Promisifying functions whose callbacks have more than two parameters

callbacks of the following functions receive more than one result value (in addition to the error value):

```js
child_process.exec;
child_process.execFile;
dns.lookup;
dns.lookupService;
fs.read;
fs.write;
```

If you promisify one of these functions, it returns an object of values (not a single value). For example, the callback of dns.lookup() has the following callback parameters:

- err : Error
- address : string
- family : integer

```js
const util = require('util');
const dns = require('dns');
const lookupAsync = util.promisify(dns.lookup);

lookupAsync('nodejs.org').then((obj) => console.log(obj));
// { address: '104.20.23.46', family: 4 }
```

### A polyfill for older versions of Node.js

There is a polyfill avaliable to take care of the older version of node servers you'll be running your application on. It can be installed via npm in the following manner:

```js
npm install util.promisify
```

Now you can patch module utl on older versions of Node

```js
const util = require('util');
require('util.promisify').shim();

const fs = require('fs');
const readFileAsync = util.promisify(fs.readFile);
```

I hope this post will make your life a tad easier. I recommend signing up to our newsletter to get the most of what's happening in the grizzly world.

Happy Grizzly 🐻 Coding
