Cancel HTTP Request by Using AbortController in Web App
Tags: javascript, axios, abortcontroller
Published: 2023-01-08 16:05:22

### Why?
In a simple way, it is to optimize our Website Performance by controlling ongoing HTTP requests, for example, users leave the page when a HTTP request is running, users want to stop their download/upload file, and many more depending on your app. So, this article may help you or me (in the future) to understand and know how to `Cancel` our HTTP Request with `AbortController` in a web Application.

### Abort Controller?
According to MDN:
> The AbortController interface represents a controller object that allows you to abort one or more Web requests as and when desired.

`AbortController` is a Class that has one `instance properties` and one `instance methods`, the instance property is `signal` and the instance method is `abort`. The `AbortController` is supported in almost all browsers except IE (but, who cares -_-). 

### Example
Here simple explanation how to use it:
```
// declare 
const controller = new AbortController();

// get signal
const signal = controller.signal;

// put signal in fetch or axios options
fetch(API, { signal });
axios(API, { signal });

// cancel request
controller.abort();
```

#### Cancel fetch in HTTP Request
In case we have a feature that can download a BIG file. To make it user-friendly, we should provide a `cancel button`.
```
let controller;

const abortBtn = document.querySelector(".abort");

abortBtn.addEventListener("click", () => {
  if (controller) {
    controller.abort();
    console.log("Download aborted");

    // Reset new AbortController, so we can do re-fetch
    controller = new AbortController();
  }
});

function fetchVideo() {
  controller = new AbortController();
  const signal = controller.signal;

  fetch(url, { signal })
    .then((response) => {
      console.log("Download complete", response);
    })
    .catch((err) => {
      if (err.name === 'AbortError') {
        console.log('successfully aborted');
      } else {
        // handle error
      }
    });
}
```

#### Cancel Request when useEffect Clean Up
The most popular AbortController usage is to clean up the useEffect function in react.js. FYI, starting from `v0.22.0` Axios supports AbortController to cancel requests, and `CancelToken` is deprecated. 
```
useEffect(() => {
  const controller = new AbortController();
  const source = controller.signal;

  axios
    .get(API, { signal })
    .catch((err) => {
      if (error.name === "CanceledError") {
        console.log('successfully aborted');
      } else {
        // handle error
      }
    });
  return () => {
    // cancel the request before component unmounts
    source.cancel();
  };
}, []);
```
One of the important thing is, errName in axios is `CanceledError` and in fetch is `AbortError`.

#### Cancel fetch Request in TypeScript react.js
this example is not really different from the first example, but sometimes we can adopt 100% js code to react.js code. And in TypeScript, sometimes, it makes more challenging to use the correct type in, what should type I use, where to find the docs, etc (:
```
import { useRef } from "react";

function Component() {
  const abortControllerRef = useRef<AbortController>(new AbortController());

  const onAbortFetch = () => {
    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
      console.log("Download aborted");

      // Reset new AbortController, so we can do re-fetch
      abortControllerRef.current = new AbortController();
    }
  };

  function getFile() {
    const signal = abortControllerRef.current.signal;

    fetch(API, { signal })
      .then((response) => {
        console.log("Download complete", response);
      })
      .catch((err) => {
        if (err.name === "AbortError") {
          console.log("successfully aborted");
        } else {
          // handle error
        }
      });
  }

  return (
    <>
      <button onClick={getFile}>Get File</button>
      <br />
      <br />
      <button onClick={onAbortFetch}>Abort</button>
    </>
  );
}

export default Component;
```
Here the [gist link ](https://gist.github.com/cakrads/9123120f8a265f1d39451f3f1105d94b), I'm not embed here cause the gist preview only show one line only.

### Conclusion
An instance of the `AbortController` class exposes the `abort` method and the `signal` property. Put the signal in options of `fetch` or `axios` then called the abort method whenever you want to cancel the HTTP request.

### Source:
- [MDN AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)