NodeJS Request Promise Guide

Introduction

NodeJS Request Promise Guide
NodeJS Request Promise Guide

We will cover everything you need to know on a NodeJS Request Promise Guide.

Did you know that you can use request are of asynchronous nature?

We will break down this in the following sections:

  • How you can benefit by using a promise to wrap your requests
  • Examples on how to make a request promise implementation
  • Alternative options using a request-promise nodejs library

I have used these methods successfully in various projects, and both work very well and has saved me a ton of trouble and time debugging things when making my requests using a promise.

We will go point by point on getting you up and running in less than 5mins; having some background programming knowledge in Javascript is helpful if you want to fine-tune our code, but you don’t need it to implement this request promise code.

This complete guide should cover all your questions on using Javascript promises to wrap your requests.

All code and examples of how to do this can be found in the Github link.

Why Use Javascript Promises For A Web Request

In this section, I’d like to cover some reasons to access why using Javascript Promises to make a web request can benefit your code. This may or may not apply to your use case, so feel free to skip this section if you know what you are doing and want to get into the coding part.

  • Promises are a nice way of catching and handling both an error case and a successful result, in the case of requests this is good because there could be various things that can go wrong so doing the error handling in one location will save you repeating the code. Some examples of why your web request can go wrong and you may need to catch this are the following:
    • Network timeout
    • Connection refused
    • Connection blocked
    • Bad request
  • As you can see wrapping all the errors in one location helps but it also helps you wrap the positive responses in one location too, some of these cases are the following:
    • Successful results but different responses
    • Different successful codes ie 200 – item received, 201 – item created etc
  • Furthermore you can map the response to whatever you want accordingly. Lets say you have no control over the remote server API and you want to map the responses to your rules you can easily do this in a promise wrapper
  • Finally a promise lets you treat asynchronous actions into synchronous with ease.

The list above is by no means, but it explains why some people may want to use promise to wrap a web request.

Why Has Request Been Deprecated In Javascript

In February 2020 request has been deprecated officially from Javascript in favor of it’s counterpart which is fetch. To be completely clear the reasoning for this is basically the list we provided above. Having the function wrapped in a promise automatically for you simply produces cleaner code and avoids a lot of boiler plate that used to come with the request function.

Timeline of Request

  • Released with the first versions in 2009
  • Asynchronous version of request introduced in 2015 called fetch
  • First notices of deprecation of request going out at around 2018
  • Officially deprecated in February 2020 in favor of fetch
  • Fetch is the standard library for making web requests as an XML HTTP wrapper function using promises

If you still on an older version for some reason of Javascript and want to use it I’m going to show you a way below for historical reasons of how to to do this. If you have no reason to stay in an older version of Javascript I recommend you go with the newer improved fetch function.

How To Setup Javascript For Promise Requests

How To Install Node and Yarn

The first step we will be doing is to set up the NodeJS environment that we will use to run our application. If you don’t have NodeJS and Yarn installed in your system I recommend checking these links to get started with those in your system:

If you are stuck in an old version of Javascript that still supports request make sure you install the right one to get the code working, otherwise it will simply not work as the function has been officially deprecated in later versions of NodeJS in favor of the fetch function which is the modern counterpart.

How To Install NodeJS Library Dependencies For Request Promise

The first step we need to do is make a directory and initialize our yarn packages there. In order to do this we will be calling the yarn init command and passing -2 so it uses version 2 structure which is faster and can parallelize package installation.

$ yarn init -2
➤ YN0000: Retrieving https://repo.yarnpkg.com/3.2.2/packages/yarnpkg-cli/bin/yarn.js
➤ YN0000: Saving the new release in .yarn/releases/yarn-3.2.2.cjs
➤ YN0000: Done in 0s 330ms
{
  name: 'nodejs-request-promise',
  packageManager: '[email protected]'
}

This initializes our repo and creates a baseline from which now we can start installing packages that we will be using in this project. So the next step is to install two packages we need here:

  • Typescript
  • Axios – Promise Request package (we will be using this later to demonstrate an alternative option of performing this operation)
  • XHR2 to use the low level XML HTTP Request function

This can be shown in the command below:

$ yarn add typescript axios xhr2
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed in 0s 269ms
➤ YN0000: ┌ Fetch step
....
➤ YN0000: └ Completed
➤ YN0000: ┌ Link step
➤ YN0000: └ Completed
➤ YN0000: Done in 0s 384ms

How To Install Development Dependencies For NodeJS

As it can be seen above we successfully installed both package dependencies, now we can proceed into installing our development dependencies that we will use in our app. The most important one is our node types so we code completion works in Visual Code alongside we will also use ts-node compiler to produce Javascript files from Typescript files.

This can be seen in the command below:

$ yarn add -D @types/node ts-node
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed in 2s 565ms
➤ YN0000: ┌ Fetch step
...
➤ YN0000: └ Completed in 0s 586ms
➤ YN0000: ┌ Link step
➤ YN0000: └ Completed
➤ YN0000: Done in 3s 179ms

How To Configure TSC For NodeJS

Finally we also need to do a final step and this is initialize the Node Typescript pseudo compiler system with some options that are good to have. Also we will be defining our source and binary directories in the command below.

$ yarn tsc --init --rootDir src --outDir ./bin --esModuleInterop --lib ES2022 --module commonjs --noImplicitAny true

Created a new tsconfig.json with:                                                                                                       TS
  target: es2016
  module: commonjs
  lib: es2022
  outDir: ./bin
  rootDir: src
  strict: true
  esModuleInterop: true
  skipLibCheck: true
  forceConsistentCasingInFileNames: true

If you notice above we also specified our default Typescript library version which in this case the latest one is ES2022, depending on which year you are seeing this on you can adjust accordingly. For now the output defaults to ES2016 so it’s compatible with various versions of Javascript.

Now that all of our dependencies and libraries are installed we can proceed into implementing some code.

How To Implement Web Request Using Fetch

Before going into the depreciated versions I’d like to demonstrate the recommend way of sending a web request with Javascript these days. The modern approach is to call the asynchronous function called fetch. Basically this handles the promise and all subsequent errors for us reducing any boiler plate code which we will demonstrate later using the old method.

Lets go ahead and show the code that implements this for us:

(async () => {
    let response;
    let request_url = 'http://localhost/my-api/request';

    response = await fetch(request_url);
    data = await response.json();
    console.log(data);
})();

By analyzing the code above we can make the following observations:

  • First we define the url for the GET REST API endpoint
  • We then call our fetch function with an await prefixed as the results may take some time to come in
  • As a next step we parse from the response and wait for the actual data to come in json format by calling the response json function
  • Finally we print out the result
  • Note in the code above you can wrap the await calls in a try/catch loop to catch any possible exceptions that may rise during the requests

Now that we have gone through the code lets see what the result of this looks like in JSON format:

[
  {
      id         : 1,
      name       : 'Unbiased Coder',
      languages  : 'Python'
  },
  {
      id         : 2,
      name       : 'Alex',
      languages  : 'Javascript'
  },
  {
      id         : 3,
      name       : 'Anna',
      languages  : 'Typescript'
  }
]

It simply shows basically a GET REST API response that returns essentially a list of users and what languages they use. Similarly in the following sections we will demonstrate this doing it in different ways such as the following:

  • Using the old deprecated request library in case your code relies on old js
  • Using the AXIOS Library
  • Using the low level XML http request function

How To Implement Request Using Promise

As mentioned earlier here we are going to demonstrate how we can implement request using a promise function. Keep in mind this is clearly for historical reasons or if you have to use an older version of NodeJS that’s compatible with your project.

In the code below this demonstrates the deprecated wrapping of the requests function into a Javascript promise:

function request_promise()
{
    let request_url = 'http://localhost/my-api/request';
    
    return new Promise(function(resolve, reject){
        request(request_url, 
            function (err, resp, body) {
                if (err)
                    return reject(err);
                try {
                    resolve(JSON.parse(body).data);
                }
                catch(e) {
                    reject(e);
                }
            }
        );
    });
}

request_promise()
.then(function(result) {
    console.log('Successfully made request with result: ', result);
})
.catch(function(err) {
    console.err('Failed making request with error: ', err);
});

Lets examine the code quickly and see what’s happening above:

  • First we create a new promise object with the reject and accept function handlers
  • Once we do this we define at a high level some error printing for the successful and error cases as shown at the bottom of the code so we know if the request succeeded or failed
  • The promise then calls the request function to fetch some json data from a REST GET API endpoint
  • We then check the return code of the request function itself and follow three different paths here:
    • First the request gave us an exception for whatever reason then we reject the promise and show the error
    • The request failed for a network or other legitimate reason such as a timeout etc
    • Finally the success case where the request succeeded, then we proceed into parsing the json response and return the data and consequently resolving the promise.

Executing the code above successfully demonstrates the same result as shown previously with the fetch function where the records are returned from our API.

How To Implement Web Request Using Axios

The next and probably one of the second recommended approaches from me to you is to use a library called Axios. This feature packed library is very good at handling requests and supports out of the box GET/POST/PUT etc REST API type requests. Furthermore it offers a lot of cool features that are beyond the scope of this article but they might be worth for you checking out if you have time separately, so I linked it at the conclusion below.

Without further delay let’s analyze the Axios implementation of what we did earlier:

const axios = require('axios').default;

(async () => {
    let request_url = 'http://localhost/my-api/request';
    response = await axios.get(request_url);
    console.log(response.data);
})();

By checking the code above lets see how it works:

  • First we import the Axios library and get an object reference to it
  • Furthermore we simply call the axios.get function to retrieve for us the JSON results
  • In this case Axios already does the JSON REST API parsing for us and puts the data available in the data property of the response object that we get back from the server
  • Finally we print out the results which basically are identical to what we did earlier

How To Implement Web Request Using XMLHttpRequest

As a final step I want to demonstrate how to get the web request data using the low level Javascript API that has pre-existed in browsers since they very early versions of Javascript and it should work across all browsers consistently.

The catch in this case is basically that it was only recently added in NodeJS which doesn’t matter as much but for demonstration purposes since we are not running in a browser we need to install the xhr library as I demonstrated earlier in this guide. If you are testing this in a browser then you should have no issue with it working as it’s already built-in.

The code that implements the above is shown here:

const XMLHttpRequest = require('xhr2');

(async () => {
    let request_url = 'http://localhost/my-api/request';
    let xhr = new XMLHttpRequest();
    xhr.open('GET', request_url, true);
    xhr.onload = function(){
        let data = JSON.parse(xhr.responseText);
        console.log('Received response: ', data);
    };
    xhr.send();
})();

Going step by step this code works as follows:

  • First we import the optional xhr library if you are running this from nodejs, if not you can ignore that line for now
  • We then create a new XMLHttpRequest object which we will be using to assemble our web request
  • The function open part of the XML Http Request library basically establishes the remote connection to the server so we can start communicating with it. It must be noted here it’s a good idea to wrap this in a try/catch because the connection may timeout or give some other network error. For simplicity and clarity of our work here I committed it but I wouldn’t run this kind of code in a production environment without error catching.
  • As a next step we define basically a callback function once the connection gets established and there’s data ready to be received. This asynchronous method basically lets the connection complete in the background while you run other things and avoid blocking your main code.
  • Finally we use the send() function to send our web request to the server
  • Once data is received in our callback we basically retrieve it from the responseText property of the response object that the callback provided to us, additionally we also convert it into a JSON object since it comes back as a text string to us. The function that can accomplish this is simply JSON.parse which is built into Javascript.
  • Printing out the result returns the same output as in the other cases.

This successfully demonstrates a low level backwards compatible method that gives you full control of making a web request in Javascript. It’s not my favorite because it has a lot of boilerplate and code that shouldn’t be implemented by most people unless they have some special use-case.

Conclusion

We were able to go over this NodeJS Request Promise Guide in an easy to explain manner with examples. Hopefully, I answered any questions you may have and helped you get started on your quest to encapsulating a web request into a Javascript promise.

Please drop me a cheer below if you found this helpful and think it may have helped you. I would appreciate it.

If you have any questions or comments, please post them below or send me a note on my Twitter. I check periodically and try to answer them in the priority they come in. Also, if you have any corrections, please let me know, and I’ll update the article with new updates or mistakes I made.

Would you consider using a library to implement your request promise or you prefer to have your own wrapper as demonstrated above?

I use this extensively for many projects when I want to have complete control over my web requests. Personally I’m always in favor of implementing my own promise wrapper for web requests since I can do a lot of custom work with it. I generally avoid libraries if there’s no need but I think the axios library which we demonstrated earlier as an alternative solution is also very good and I’d highly recommend using it if you want to get started fast in your project without doing a lot of custom things.

If you would like to find more articles related to API related stuff and web requests you can check the articles below:

You can find information about relevant projects referenced in this article in the list below:

Leave a Comment

Your email address will not be published. Required fields are marked *