How to Wrap Node's HTTPS in a Promise

Node's HTTPS package is very low level. It expects you to provide functions to deal with data as it streams in, and it doesn't provide a simple interface to get the data out once it has all arrived. One way to add a neat interface to Node's HTTPS package is with Promises.

Here's one basic way to use the HTTPS package. We have to provide a couple of listener functions that know what to do when a new data event occurs (concatenate the data into a buffer) and what to do when an end event occurs (print the data out).

const https = require('https');

https.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', (resp) => {
  let data = '';

  // A chunk of data has been received.
  resp.on('data', (chunk) => {
    data += chunk;
  });

  // The whole response has been received. Print out the result.
  resp.on('end', () => {
    console.log(JSON.parse(data).explanation);
  });

}).on("error", (err) => {
  console.log("Error: " + err.message);
});

This is pretty verbose. We can wrap all this in a function that returns a promise. That way we can hide a good deal of the implementation details of the HTTPS interface behind an abstraction of our choice. One way to do that looks like this:

const https = require('https');

const get = (url) => {
  return new Promise((resolve, reject) => {
    https
      .get(url, (response) => {
        let data = "";

        // A chunk of data has been received.
        response.on("data", (chunk) => {
          data += chunk;
        });

        // The whole response has been received. Print out the result.
        response.on("end", () => {
          resolve(JSON.parse(data));
        });
      })
      .on("error", (error) => {
        reject(JSON.parse(error.message));
      });
  });
};

This new get function returns a promise that resolves with the parsed JSON of the response when the request is successful or rejects with an error message. This function is a bit complicated, but it's much easier to use! Take a look at the code below that uses it:

const url = "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY";
get(url).then((data) => {
  console.log("data", data);
});

Much better! As you can see, promises aren't that hard to create. You just have to do three things:

  1. Create and return a new Promise.
  2. Pass the promise object a function that takes two parameters: a function named resolve, and a function named reject.
  3. Inside the body of the function we pass to the promise, do whatever work you want to do. When you're done and everything was successful, call the provided resolve function and pass it the final result of your computations. If the work was not successful, call the provided reject function and pass it whatever error value you like.

Photo by Payam Tahery