convert callback to promise

How to Convert Callback to Promise in NodeJS

NodeJS is a popular javascript based web development framework. It supports callbacks in functions that allow you to handle requests asynchronously. However, it is easier to work with Promises offered by newer versions of NodeJS. But most of the old NodeJS modules and APIs use callbacks. So how do you convert your old NodeJS code to use promises? In this article, we will look at how to convert callback to promise in NodeJS.


How to Convert Callback to Promise in NodeJS

Here are the steps to convert callback to promise in NodeJS.

Callbacks are basically function definitions passed as the last argument of a NodeJS function. Here is an example of callback with function fs.readFile

const fs = require('fs')  
fs.readFile(filePath, options, callback)

Each callback needs to have 2 arguments with an error object as its first argument.

fs.readFile('filepath', (err, data) => {
  if (err) {
    // Handle error 
  } else {
    // Do something with data
  }
})

Also read : How to Create Virtual Host in WAMP


Callbacks that follow the above pattern can be converted into promises using Promisify utility. Here is an example to convert fs.readFile function into a Promise.

const fs = require('fs')
const util = require('util')
const read_file_promise = util.promisify(fs.readFile)

Thereafter, you can use it like any NodeJS promise.

read_file_promise(filePath, options)
  .then(data => {/* Do something with data */})
  .catch(err => {/* Handle error */}

Please note, promisify utility works only with callbacks whose structure is similar to that of a promise. In other words, a callback must have the pending-completion-reject flow. As you can see the if..else condition for err and data are similar to reject and completion state of promise. That is why, util.promisify works for us.

Also read : How to Enable CORS in NodeJS


What should you do if your callback does not follow this model? In such cases, you need to write your own promise separately. Here is an example of a promise in NodeJS.

const read_file_promise = () => {
  return new Promise ((resolve_handler, reject_handler) => {
    // ...  
  })
}

Once you have written the promise, add the function with callback code to it.

const read_file_promise = () => {
  return new Promise((resolve_handler, reject_handler) => {
    fs.readFile(filePath, options, (err, data) => {
      // ...
    })
  })
}

Please note, in the above callback function, you can swap err & data, and it will still work. In other words, even if your callback does not follow the default callback strucure in NodeJS, still it will work.

const read_file_promise = () => {
  return new Promise((resolve_handler, reject_handler) => {
    fs.readFile(filePath, options, (data, err) => {
      // ...
    })
  })
}

Now we need to reject the promise if there is an error, continue processing in case there are no errors. So modify the above code as shown below. It allows you to call reject_handler in case of errors, and call resolve_handler in case there are no errors.

const read_file_promise = () => {
  return new Promise((resolve_handler, reject_handler) => {
    fs.readFile(filePath, options, (err, data) => {
      if (err) return reject_handler(err)
      resolve_handler(data)
    })
  })
}

Also read : How to Disable HTTP Strict Transport Security Policy


Finally, you need to pass the arguments to callback via promise. You can do this via NodeJS rest and spread operators as shown.

const read_file_promise = (...args) => {
  return new Promise((resolve_handler, reject_handler) => {
    fs.readFile(...args, (err, data) => {
      if (err) return reject_handler(err)
      resolve_handler(data)
    })
  })
}

Now you will be able to use readFilePromise as a normal NodeJS promise.

read_file_promise(filePath, options)
  .then(data => {/* Do something with data */})
  .catch(err => {/* Handle error */}

In this article, we have seen how to convert NodeJS callback into promises.

Also read : How to Increase Request Timeout in NodeJS


Leave a Reply

Your email address will not be published.