Steve Breese

A Chicago-based Full-stack JavaScript Developer

Node.js Tutorial: Promisify your Node.js Callback Functions

Below is a quick tutorial on how to use promisify() to convert a callback-based function to a Promise-based one. Promises offer more flexibility to developers than callbacks and help you write cleaner, easy-to-ready code.

  1. Identify a Node.js callback function that should be converted to a promise. In this tutorial, we will convert a simple function that takes an image path as its only parameter and returns the images width and height in a JavaScript object.
    const sizeOf = require('image-size');
    sizeOf(path.join(form.uploadDir, file.name), function (err, dimensions) {
        console.log(dimensions.width, dimensions.height);
        if (err) {
             console.log(`[Error]: ${err}`);
        }
    });
                            
  2. Add the Node.js Util module to the top of your JS file.
    const util = require('util');
    
    var sizeOf = require('image-size');
    sizeOf(path.join(form.uploadDir, file.name), function (err, dimensions) {
        console.log(dimensions.width, dimensions.height);
        if (err) {
             console.log(`[Error]: ${err}`);
        }
    });
    
  3. Wrap the original callback function (in this case, the image-size require statement returns a single function) with the promisify utility, which converts it to a function that returns a promise. Delete the old require statement.
    const util = require('util');
    const sizeOfAsync = util.promisify(require('image-size'));
    
    var sizeOf = require('image-size');
    sizeOf(path.join(form.uploadDir, file.name), function (err, dimensions) {
        console.log(dimensions.width, dimensions.height);
        if (err) {
             console.log(`[Error]: ${err}`);
        }
    });
    
  4. Replace your callback function call with the new promisified function and delete the ES5 function expression or ES6 arrow syntax.
    const util = require('util');
    const sizeOfAsync = util.promisify(require('image-size'));
    
    sizeOfAsync(path.join(form.uploadDir, file.name))
    sizeOf(path.join(form.uploadDir, file.name), function (err, dimensions) {
        console.log(dimensions.width, dimensions.height);
        if (err) {
             console.log(`[Error]: ${err}`);
        }
    });
    
  5. Add the Promise's then statement and move the callback's return argument and its code from the callback body to the then body.
    const util = require('util');
    const sizeOfAsync = util.promisify(require('image-size'));
    
    sizeOfAsync(path.join(form.uploadDir, file.name))
        .then(dimensions => {
            console.log("Image dimensions:", dimensions.width, dimensions.height)
        })
     (err, dimensions) {
        console.log("Image dimensions:", dimensions.width, dimensions.height);
        if (err) {
             console.log(`[Error]: ${err}`);
        }
    });
    
  6. Lastly, add the Promise's catch statement and move the callback's error argument and its code from the callback body to the catch body.
    const util = require('util');
    const sizeOfAsync = util.promisify(require('image-size'));
    
    sizeOfAsync(path.join(form.uploadDir, file.name))
        .then(dimensions => {
            console.log("Image dimensions:", dimensions.width, dimensions.height)
        })
        .catch(err => console.error(`[Error]: ${err}`));
        if (err) {
             console.log(`[Error]: ${err}`);
        }
    
  7. After the conversion, the resulting Promise code should look like the following:
  8. const util = require('util');
    const sizeOfAsync = util.promisify(require('image-size'));
    
    sizeOfAsync(path.join(form.uploadDir, file.name))
        .then(dimensions => {
            console.log("Image dimensions:", dimensions.width, dimensions.height)
        })
        .catch(err => console.error(`[Error]: ${err}`));
    

With these changes, we have converted a callback function to a promise and demonstrate how to use the new promise. Now go ahead and replace all your Node.js callback functions with promises to have cleaner and easier to read code.