Practical use case of the Abortcontroller and Axios cancel token
Published: 2021-09-01 15:29:02

## Introduction
When implementing functionalities that involve making API requests, there are occasions where we need to cancel a pending request either based on the feature requirements or to prevent unexpected behavior in our application.

Some of these occasions include:

- Providing users the ability to cancel a pending request.
- Aborting an ongoing request when a user leaves a page.
- Canceling pending requests before making a new one when the input changes.
                         
To handle scenarios like these most modern browsers have an inbuilt AbortController interface that allows you to cancel one or more API requests when using the  [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). 

The  [Axios](https://axios-http.com)  HTTP client package handles API request cancellation using its cancel token API which is based on the withdrawn  [cancelable promises proposal](https://github.com/tc39/proposal-cancelable-promises).

## Goal
To demonstrate how to cancel API requests using the Fetch API and Axios cancel token, we will be implementing an autocomplete search functionality.

The autocomplete search will make an API request every time a user enters a value in the search bar.

This feature will demonstrate how to cancel pending API requests before making a new one, every time the content of the input changes.

Our implementation flowchart:
![autocomplete search flowchart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmfivxltsff8e8j74aaj.png)

Before we proceed to our implementation let us create the search input field then add an event listener and the listener callback.

First, we will select the search input field:

```
const input = document.querySelector('#search');
``` 
We then add an event listener to the search field and a `searchItems` callback which gets called on input change

```
input.addEventListener('input', searchItems);
```

The `searchItems` callback function will be implemented using the Fetch API and axios with each line commented to explain what they do.

## Fetch API implementation
Before making an API request we’ll create a controller using the `AbortController()` constructor, then grab a reference to its associated `AbortSignal` object using the `AbortController.signal` property.

When the fetch API request is initiated we pass the `AbortSignal` as an option inside the requests options object, this associates the signal and controller with the fetch request and allows us to abort it by calling `AbortController.abort()`.

It is important to note that when the `abort()` method is called the `fetch()` promise rejects with a `DOMException` named `AbortError`. We can use the `DOMException` name to know if an error occurred due to request cancellation.

Let us proceed with the implementation, with each line commented to explain what they do.

```
...

let controller;

function searchItems(event) {
    // Grab the user input from the input event param
    const query = event.target.value;

    // Check if an AbortController instance has been assigned to the controller variable, then call the abort method when true.
    // To cancel a pending request the abort() method is called.
    if (controller) controller.abort();

    // A new instance of the AbortController is created before making the API request
    controller = new AbortController();

    // grab a reference to its associated AbortSignal object using the AbortController.signal property
    const signal = controller.signal;

    // We pass in the AbortSignal as an option inside the request's options object
    fetch(`https://example.com?name=${query}`, {signal})
        .then(function(response) {
            console.log(response);
        }).catch(function(e) {
        // Check the exception is was caused request cancellation
        if (e.name === 'AbortError') {
            // handle cancelation error
        } else {
            // handle other error
        }
    })
}
```

## Axios implementation
To cancel an ongoing request using axios the `cancel(...)` method from the cancel token API which takes an optional parameter for a message is invoked.

Before making an API request, a cancel token will be generated and passed as an option to the axios config. The token associates the current request and the `cancel(...)` method.

When an axios promise rejects due to cancelation, the `axios.isCancel(...)` method which takes the exception as an argument is used to check if the exception was due to cancellation.

Let’s proceed with the implementation, with each line commented to explain what they do.

```
...

// create a source variable which we will later assign cancel token using the CancelToken.source factory.
let source;

function searchItems(event) {
    // Grab the user input from the input event param
    const name = event.target.value;


    // Check if a CancelToken.source has been assigned to the source variable, then call the cancel method when true.
    if (source) source.cancel('Operation canceled by the user.');

    // Assign the source factory to the source variable
    source = axios.CancelToken.source();

    const option = {
        params: { name }, // Pass query strings via param option
        cancelToken: source.token // add the cancel token, as an option for the request
    };

    axios.get('https://example.com', option)
        .then((response) => {
            console.log(response)
        })
        .catch(function (thrown) {
            if (axios.isCancel(thrown)) {
                console.log('Request canceled', thrown.message);
            } else {
                // handle error
            }
        });
}
```
## Conclusion

In this tutorial, we have learned how to cancel a Fetch API and Axios request by implementing an autocomplete search functionality. I hope with this implementation, you will be able to create your request cancellation functionality as the need may be.

## Additional Resources
- [AbortController - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) 
- [Cancellation | Axios Docs](https://axios-http.com/docs/cancellation)