How do I convert an existing callback API to promises?

Frontend.LA

a year ago

If you are writing a lot of Node.js or just getting started and you will realize that all async code and most examples on npm make use of callbacks

var request = require('request');
request('http://www.google.com', function (error, response, body) {
  console.log('body:', body); 
});

But consider a scenario where you make :

  1. API call #1
  2. Pass the response of API call #1 to API call #2
  3. Pass the response of API call #2 to API call #3

To accomplish that using the sample code above from npm for "request" you will end up with code like this:


request('http://www.example.com/api/call1', function(error, response, body) {
    request('http://www.example.com/api/call2?userId=body', function(error, response, body) {
        request('http://www.example.com/api/call3?productId=body', function(error, response, body) {
            console.log('body:', body);
        });
    });
});

Will it work? Yes. However, it consists of multiple nested callbacks which makes it hard to read, debug and test. Code like this with nested callbacks is also referred to as callback hell. 

During the initial stages of the project, this kind of code may seem harmless however as the project grows and 5 engineers follow this pattern all over the place, you will end up in an undesirable situation.

A better way to handle this would be converting your callback methods to promises and use async-await e.g.

const request = require('request'); 
const makeRequest =(url) => {
    return new Promise(function(resolve, reject) {
        request(url, function(error, response, body) {
            if (error)
                reject(error)
            else
                resolve(body)
        });
    });
}

const resultCallOne = await makeRequest('http://www.example.com/api/call1')
const resultCallTwo = await makeRequest('http://www.example.com/api/call2?userId=' + resultCallOne.userId)
const resultCallThree = await makeRequest('http://www.example.com/api/call2?productId=' + resultCallTwo.productId)