Promise, Promisification, Promisify Function

Sep 17, 2021
5 min read

Promisification word may sound complicated but it belongs to a simple transformation. This procedure basically converts a function that accepts a callback, into a function that returns a promise. This type of transformation is needed more often because you will find many functions and libraries callback-based.

Indeed, Promisify benefits the development as the use of promise is convenient.

Promise is an object and an alternative for a callback. With promise, you can handle asynchronous operations.

Deeply nested structures formed by callbacks produce more maintainable code when converted to promises.

The Promise constructor converts callbacks into promises.

The Promise constructor is required to convert a callback to a promise. The callback of the Promise constructor takes two arguments: resolve and reject.

Resolve callback should be invoked when the async operation has been completed. On the other hand, if there is an error then the reject callback is invoked.

You will get the Promise instance from the constructor. 'then' is the method that notifies when the promise is completed. Promises actually do asynchronous callbacks and you can chain multiple async operations with it.

Promises have a tendency to handle errors more elegantly.

Before knowing how to convert callbacks to promises, you should also note what I have mentioned below.

See the snippet below, which shows that once a promise is resolved, it can no longer be rejected, i.e. out of resolve and reject, one method will be valid and only one method will be called.

Let us now look at the different stages of promise

Pending: When the async operation is running, i.e. still in progress.

Fulfilled: Here the operation is successful and after that "then" callback will be invoked.

Rejected: The operation has failed. If it fails, it will invoke ".catch(onError)" and ".then(..., onError)".

Settled: Resolve and Reject callbacks no longer work here. Only .finally method is invoked here.

The Promise API gives you three main methods. They are: then, catch and finally.

When the asynchronous operation completes, the "then" method is invoked to notify you of the completion. The "then" method lets you know both success and failure. That is, it has two arguments: one for successful execution and another for error.

promise.then(onSuccess, onError);

Apart from this catch can also be used, something like:

promise.then(onSuccess).catch(onError);

Multiple promises can also be chained with "then" because it returns a new promise.

Promise.resolve resolves the promise and will stop executing if the error breaks the sequence.

Finally method

If the promise is settled then finally method will be called.

You can use "then" as well as "finally" if you need to execute a piece of code after a failure.

Promisification

loadMyScript is given the src to load the script. If an error occurs then callback(error) is called otherwise if no error occurs then callback(null, script) is called.

Now it's time to promisify.

For this, I created a function here. It will load the script as well. But here the promise will be returned, and not the callbacks.

This new function is a wrapper of the original loadMyScript function.

The loadMyScript function that receives the callback from this wrapper function translates to promise resolve/reject.

Our new function loadMyScriptPromise is a perfect fit for promise-based code.

It is not a matter of liking the promises more than callbacks, but rather some specific reasons which you will come to know while practising. Let me also discuss the points here:

  1. If you implement the callbacks and do something sequentially, then you have to specify an err argument in each callback. This is redundant. In a promise or async-await, you add a catch method or block. Now if there is an error in the chain of promise, it is caught.
  2. Callbacks can cause memory leaks. Because you don't have control over it. When it would be called and under what context. And how many times. You don't know!
  3. We don't face such problems with promises, especially if we talk about error handling.
  4. Your code is also more readable and maintainable.

Note: Promise is definitely a good approach when it comes to async/await. Even so, it cannot completely replace callback. Promise has only one result whereas callback can be called multiple times. That's why promisification is used only for those functions which call the callback once.

One way is that you have to wrap a function around the original function which will return the promise. And another way is when we want to promisify more than one function. For this, we will use the helper which is a sensible way.

The code is complex to look at, otherwise, it is the same code that is written above when we are promisifying the loadMyScript function.

promisify(f) is our helper function that accepts the function we have to promisify.

You can see that it is returning a wrapper around f (*). The wrapper is also returning a promise and then the call goes to original f. Here the original f expects a callback with only two arguments. You can further modify the code to accept more arguments.

Finally, I will discuss the Promisify function in Node.js and wrap up this article

Being a Node.js developer means you already know about Promise. And especially how it works internally. You will find more modules to promisify functions such as es6-promisify. Node.js has built-in util.promisify function. The built-in util package in Node.js provides you with utility functions. In these utility functions, you get the promisify() function which enables you to use promise chaining and async/await.

fs.readFile function to be promise-based