Cancelling an Async Promise with AbortController

2 min read

Cancelling an Async Promise with AbortController

In this post, we will be looking into AbortController and how can we use it to cancel network requests.

We know that fetch is a method that sends a network request and returns a promise, but what if we wanted to cancel this ongoing request.

For example, consider this scenario where we want to implement a search functionality that displays results during user input, however user typing speed can vary from one to another and we want to cancel the preceding request. We can do it by minimising the number of server requests using AbortController.

Syntax

AbortController is an object (controller object) that allows you to abort one or more requests (async requests) when needed.

  • signal property which allows setting event listener on the property.

  • abort() method which will set the signal aborted flag.

  • So when abort() method is called, it will cancel the DOM request before it has been completed and setting the aborted flag to true.

Usage

In order to cancel a fetch request generally, we need to perform 3 steps:

  1. Create an AbortController instance which has a signal property (read-only property)

    1
    // creare new object instance of abortContoller
    2
    let aborter = new AbortController();
  2. Pass the signal property as a fetch option for signal

    1
    // we get the signal and pass it to the fetch request as param
    2
    let signal = aborter.signal; // signal is read only
    3
    const url =
    4
    "https://api.github.com/search/repositories?q=stars:%3E1+language:javascript&sort=stars&order=desc&type=Repositories";
    5
    fetch(url, {
    6
    method: "GET",
    7
    signal,
    8
    })
    9
    .then((response) => response.json())
    10
    .then((res) => {
    11
    aborter = null;
    12
    return res;
    13
    })
    14
    .catch((error) => {
    15
    if (error.name === "AbortError") return;
    16
    console.log("Error ", error);
    17
    });
  3. Call abortController’s abort() method to cancel all fetches that are pending which use the signal.

    1
    aborter.abort();

Example

The following snippet shows how to use abortController with fetch. Here is the full example:

abortController

1
let aborter = null;
2
const getRepos = (lang) => {
3
// cancel pending request if there is any
4
if (aborter) aborter.abort();
5
aborter = new AbortController();
6
let signal = aborter.signal;
7
const url = `https://api.github.com/search/repositories?q=stars:%3E1+language:${lang}&sort=stars&order=desc&type=Repositories`;
8
return fetch(url, {
9
method: "GET",
10
signal,
11
})
12
.then((response) => response.json())
13
.then((res) => {
14
aborter = null;
15
return res;
16
})
17
.catch((error) => {
18
if (error.name === "AbortError") return;
19
console.log("Error ", error);
20
});
21
};
22
// the first call will be aborted
23
getRepos("javascript").then((res) => {
24
console.log(res);
25
});
26
getRepos("python").then((res) => {
27
console.log(res);
28
});

The reason we are defining the aborter variable outside the function scope so that regardless of how many times the function is called or how many requests are still pending, it will only display the results of the last request that was submitted.

And here you can see the example above in action with the first call being aborted and the second one going through.

networkRequests

Conclusion

In this post, we looked at AbortController and how can we use it to cancel network requests with an example usage with fetch.