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
- What are Node.js modules?
- HTTP - Standard Library Module
- Request
- Axios
- Fetch
- 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:
- HTTP Standard Library
- Request
- Axios
- 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 addContent-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.
#1 Solution for Logs, Traces & Metrics
APM
Kubernetes
Logs
Synthetics
RUM
Serverless
Security
More