How to cancel an HTTP request in Node.js?

Node is an open-source, cross-platform JavaScript run-time environment for developing server-side and networking applications.

A peculiar feature of Node.js is its ability to process concurrent requests without delay. It uses an asynchronous programming method for doing so.

Usually, when handling a request, the program sends this request to the computer’s file system. It then opens the requested file, reads it and then returns the content to the client.

During this entire process, it will not be able to take in additional requests i.e., it can handle only one request at a time.

But in node.js, the asynchronous programming allows the client to put in another request during this wait time. Thus, reading the file and processing the request for the next file happen concurrently.

Table Of Contents

  1. What are Node.js modules?
  2. HTTP - Standard Library Module
  3. Request
  4. Axios
  5. Fetch
  6. Using AbortSignal with setTimeout() to cancel requests in Node.js

What are Node.js modules?

Node.js modules are JavaScript libraries that can be used in Node.js applications to provide specific functionality. Node operates with several modules that allow us to reuse the code in our application.

It is a way of grouping up different types of functionality together in a single file called a module. The idea behind modules is that each module does one thing and does it well, without trying to do everything.

Node.js modules are placed in the node_modules folder. When you require a module, Node.js will look in the node_modules folder and find the module you are looking for.

There are a wide variety of node modules available, including modules for HTTP, file system, database access and so on.

Four major modules to make HTTP request

In Node.js, making a HTTP request is a breeze. There are a few different ways to go about it, but we'll focus on the four most popular methods:

  1. HTTP Standard Library
  2. Request
  3. Axios
  4. Fetch

Each of these modules has a different purpose and is responsible for a different aspect of the HTTP request process. In this blog post, we'll take a closer look at each of these modules and how they work together to make HTTP requests.

We will learn how to make and cancel HTTP requests using these modules in the steps below.

1. HTTPS Standard Library

Node.js has a default built-in module called HTTP, which allows Node to transfer data over the HyperText Transfer Protocol and it is a standard library module. This module comes bundled with Node.js, you do not need to install any external dependencies.

Making a HTTP request

First, you need to require the HTTP module. This module has all the functions you need to create a HTTP request.

const https = require('https');

This doesn't require a package.json file or any npm install --save command.

const https = require('https'); 

https.get(API_URL, (res) => { });

Here is the code that sends the GET request to an API and print out the response of it.

The request is executed over http GET method and the data is gathered into the variable data as it is received. Data is parsed and logged on the console once it has been received.

const https = require('https');

let options = {
    host: 'www.devtools.com',
    path: "/blog/monitoring-tools/",
    method: 'GET',
    signal: { signal }
};

https.request(options, (err, res) => {
    if (err) {
        console.error("Error message:", err);
        return;
    }
    let data = '';
    res.on('data', (chunk) => {
        data += chunk;
    });
    res.on('end', () => {
        console.log('Retrieved all data', JSON.parse(data));
    });
});

We don't need to call .end() method every time since .get() automatically calls .end().

Cancelling a HTTP request

Asynchronous processes take a lot of time to produce a response. Meanwhile, you may want to cancel a particular request or even cancel the entire results. In such a case, cancelling out these APIs is our only option. But it is not as easy as it sounds.

The AbortController API is a saviour in such instances, it allows you to cancel a particular request or even the entire program using its abort function.

Following is a JS file created to show how Abort API works in the Node.js program. The file will be saved as index.js

const https = require('https')
const AbortController = require("abort-controller")

const controller = new AbortController();
const signal = controller.signal;

let options = {
    host: 'www.devtools.com',
    path: "/blog/monitoring-tools/",
    method: 'GET',
    signal: { signal }
};

https.request(options, (err, res) => {
    if (err) {
        console.error("Error message:", err);
        return;
    }
    let data = '';
    res.on('data', (chunk) => {
        data += chunk;
    });
    res.on('end', () => {
        console.log('Retrieved all data', JSON.parse(data));
    });
});

// Cancel the request
controller.abort();

In most cases, HTTP and HTTPS modules perform low-level functionality. The response data must be received in chunks, rather than simply providing a callback function to be executed when all of the data is received.

The response data also needs to be manually processed. If the data is JSON formatted, this step is fairly straightforward, but it is still a hassle.

Furthermore, this module doesn't support HTTPS by default, so if the API we're using communicates over HTTPS, we need to require the https module instead.

Compared with other modules, it is not very user-friendly, which is why it is not very popular nowadays.

2. Request

The request module is one of the most popular modules in Node.js. It allows you to make HTTP requests from your Node.js application. In comparison to HTTP module, it is more user-friendly and is regarded as safer due to its large community.

Making a HTTP request using Request module

In order to use the request module in Node.js, you must first install it. You can do this by using the following command:

npm install request

Once you have installed the request module, require the request module and then you can now use it in your Node.js program as given below:

const request = require('request')

A request for HTTP can be made by passing a configuration object or just the URL along with a callback function to the request() method.

The url property of an object must be specified; if no method is specified, GET is used by default. A simple example would be as follows:

const request = require('request')
  
// Request URL
var url = 'http://myshop.com/api/books';
 
request(url, (error, response, body) => {
    
    if(error) console.log(error)
   
    console.log(response.statusCode);     
    console.log(body);
});

In the above code, we request the list of books from our fake API using a GET request. A console output is generated after parsing the returned JSON response.

There are two types of parameters for the request() function: URL strings and object literals. You can configure the object with the following options:

  • url — Request's destination URL.
  • method — One of the HTTP methods, such as GET or POST.
  • headers — Object of key-value pairs.
  • json — Shortcut to add Content-type: application/json header. Parses the response body as JSON.

Here is an example with options object in the request module:

const request = require('request');

const options = {
    url: 'https://www.myshop.com/books',
    method: 'GET',
    headers: {
        'Accept': 'application/json',
        'Accept-Charset': 'utf-8'
    }
};

request(options, function(err, res, body) {
    let json = JSON.parse(body);
    console.log(json);
});

Request is one of the easy way to create a HTTP call and if you want to use it with a promise you can check for the request-promise library.

To abort a HTTP reuest in Request module

Having the ability to abort a HTTP request in Request module is one of the skills that can go a long way in helping developers achieve their goals. By understanding how to abort a HTTP request, developers can have greater control over their web development process.

One way to ensure secure applications is to know how to abort HTTP requests in the Request module. This can make sure that no malicious code is executed or access to unwanted data is gained.

With request module you can easily abort a request:

const request = require('request');

const options = {
    url: 'https://www.myshop.com/books',
    method: 'GET',
    headers: {
        'Accept': 'application/json',
        'Accept-Charset': 'utf-8'
    }
};
let req = request(options, function(err, res, body) {
    let json = JSON.parse(body);
    console.log(json);
});

req.pipe(parser);

req.abort();

3. Axios

The Axios module is a promise-based HTTP client that provides a simple and straightforward way to make HTTP requests in Node.js.

It can be used to make both asynchronous and synchronous HTTP requests and that is why it is called Isomorphic which means it can run in both Node.js and browser in the same codebase.

It has a convenient and modern API simplifying asynchronous HTTP request and response handling. We'll also be looking at some examples of how to use the Axios module to make GET request.

Making a HTTP request using Axios

To use axios we have to install it first with the command:

npm install axios

After installing the module, require the axios module:

const axios = require('axios');

With the code below, we sent a HTTP request to http://myshop.com after configuring the configuration options before sending the request.

const axios = require('axios');

async function makeRequest() {
    try {
      const response = await axios.get('https://www.atatus.com/blog/cloud-monitoring/');
      console.log(response);
    } catch (error) {
      console.error(error);
    }
  }

makeRequest();

Cancelling an axios HTTP request

There are two ways to cancel the ongoing axios HTTP request.

i.) Using AbortController

ii.) Using CancelToken

We will see how to cancel a HTTP request using AbortController in this here.

Using AbortController

Abort() is a JavaScript API allows you to cancel an outgoing request, which can be useful if you need to abort a request for any reason. It consists of an AbortController class and an Abortsignal class.

AbortController() - AbortController represents a controller object which allows you to abort requests in any program. It has a single Abort() method and a single signal.Property that allows to set EventListeners on it.

// syntax

const controller = new AbortController();

Using AbortController constructor, create a controller, then refer the AbortSignal object using AbortController.signal property.

Abort Signal - Signal.property allows you to add AbortSignal class to the AbortController class.

AbortSignal class can extend the eventTarget and receive the abort event. Thereafter, you can add or remove listeners to this event using addEventListener and removeEventListener methods.

Apart from adding events, AbortSignal has other functions like abortSignal.timeout method for cancelling an event after a certain amount of time.

// syntax

const controller = new AbortController() const abortSignal = controller.signal

Complete Example:

const axios = require('axios');
const AbortController = require("abort-controller")
const controller = new AbortController();


async function makeRequest() {
    try {
      const response = await axios.get('https://www.atatus.com/blog/cloud-monitoring/', {
        signal: controller.signal
     });
      console.log(response);
    } catch (error) {
      console.error(error);
    }
  }

// cancel the request
controller.abort()

4. Fetch

The Fetch API has become increasingly popular over the past few years as a way to access data from websites and other sources. It acts as an interface across networks for fetching resources in response to a request.

It provides an easy way to make network requests and allows for simple error handling. Nodejs has implemented the Fetch API in its core and provides a simple, consistent way to access data from external sources.

Let's explore the fetch() API in Node.js and discuss how it can be used to create more efficient web applications.

How to make a request using fetch API?

Installing fetch in node using npm package manager:

npm install node-fetch

Syntax:

fetch(resource) fetch(resource, options) 

The resource parameter in fetch can be any object with a stringifier. The resource object must be a string. It can even be an URL object.

The options can include any request that you want to be fetched. For example, get, post, headers, mode, omit, include, cache, redirect, referrer etc.

fetch(url)
    .then((response) => {
    	return response.json();
	})
    .then((data) => {
    	console.log(data);
	})

Example:

import fetch from 'node-fetch';

async function makeRequest() {
    try {
      const response = await fetch('https://www.atatus.com/blog/cloud-monitoring/')
      console.log(response);
    } catch (error) {
      console.error(error);
    }
  }

makeRequest()

How to cancel an ongoing fetch using Abort API?

In order to cancel the fetch() request, we first input the signal property of AbortController as a fetch option:

let controller = new AbortController();
fetch(url, {
  signal: controller.signal
});

Using the abort() function in AbortController makes the fetch request to listen to the signal and abort the event.

Thus for aborting the fetch request, call controller.abort():

controller.abort();

Fetch gets the signal and aborts the request.

Using AbortController and signal.properties in fetch API for a URL object:

import fetch from 'node-fetch';

const url = "https://www.pexels.com/search/beautiful/";

const controller = new AbortController();
const signal = controller.signal;

function downloadImage() {
    fetch(url, { signal })
        .then(function (response) {
            console.log(response.status);
        })
        .catch(function (e) {
            console.error(e);
        });
}

function abortDownload() {
controller.abort();
}

‌After the Abort event, the removeEventListener class is used to remove the asynchronous process to prevent any further memory loss.

The APIs that can be cancelled at the moment include - Fetch API(), SetTimeout(), HTTP and HTTPS requests and fs.readfile and fs.writefile.

Using AbortSignal with setTimeout() to cancel requests in Node

Here, we use the promise variant of setTimeout(). Asynchronous operations can be cancelled at the scheduled time using this function.

Importing the modules from node fetch:

import fetch from "node-fetch";
import { setTimeout } from "node:timers/promises"; 

Creating AbortController instances for cancelling the request and Timeout.

const cancelRequest = new AbortController();
const cancelTimeout = new AbortController();

Making an HTTP request

async function makeRequest(url) {
  try {
    const response = await fetch(url, { signal: cancelRequest.signal });
    const responseData = await response.json();
  return responseData;
  } finally {
    cancelTimeout.abort();
  }
}   

Here, the HTTP request that fetch() made, gets aborted due to the AbortSignal - cancelRequest.signal

Creating setTimeout function

async function timeout(delay) {
    try {
        await setTimeout(delay, undefined, {
            signal: cancelTimeout.signal
        });
        cancelRequest.abort();
    } catch (error) {
        return;
    }
    throw new Error(`Request aborted as it took longer than ${delay}ms`);
}

‌The signal option cancelTimeout.signal is passed in the AbortController. This allows us to abort the timeout request by calling cancelTimeout.abort() method.

After encoding makeRequest and setTimeout functions we put it under promise.race()

const url = "https://jsonplaceholder.typicode.com/posts";

const result = await Promise.race([makeRequest(url), timeout(100)]);
console.log({ result });

Here we have set the timeout for 100 milliseconds. If the HTTP request completes within that time, the value of the result would be parsed JSON response body. Thus, the timeout will be aborted.

Meanwhile, if the request is not completed within 100 milliseconds, Timeout() function will abort the HTTP request and emit an error.

Conclusion

Asynchronous processes allow faster compilation of requests, but many a time, they fall short of the time required to do so. In such instances, we would want to delete the request or even cancel the entire request stack.

Cancelling an HTTP request has been a daunting task all this while. But this new AbortController API in Node helps us deal with this problem.

Coupled with AbortSignal , the Abort APIs are a boon to the developers. The signal.property of AbortSignal passed onto a cancellable API can invoke the controller’s Abort method. And finally, it aborts the request made by the controller.

Also, be careful to remove the EventListener after Abort method to prevent any memory leakages.


Monitor Your Node.js Applications with Atatus

Atatus keeps track of your Node.js application to give you a complete picture of your clients' end-user experience. You can determine the source of delayed response times, database queries, and other issues by identifying backend performance bottlenecks for each API request.

Node.js performance monitoring made bug fixing easier, every Node.js error is captured with a full stack trace and the specific line of source code marked. To assist you in resolving the Node.js error, look at the user activities, console logs, and all Node.js requests that occurred at the moment. Error and exception alerts can be sent by email, Slack, PagerDuty, or webhooks.

Try Atatus’s entire features free for 14 days.

Aiswarya S

Aiswarya S

Writes technical articles at Atatus.

Monitor your entire software stack

Gain end-to-end visibility of every business transaction and see how each layer of your software stack affects your customer experience.