# Abort Controller: How To Stop Processing Duplicate Requests Out of Order

To do something asynchronous in JavaScript you typically need to use a `Promise`.

Need to open a local file?

Need to make an API request using fetch?

Want to wrap `setTimeout` to use with `async / await`?

You can use a promise. It's a common pattern that's used everywhere. The `Promise` pattern is a way to clean up your code so it's easier to write and understand.

## The Problem

Ok. But, what happens if we fire off an async task and then no longer care about the result of the `Promise`?

Let's say I made the same API request two times in a row. I don't care about the result of the first one, but API requests are async. They might come back in the wrong order.


![OutOfOrderRequests.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661382426272/mBV8aQJD4.png align="left")

So what?

It might not seem like a big deal, but if I'm displaying data from an API in the browser, the user could end up in a weird state.

For example, let's say my application has a list with a set of filters. Every time I change the set of filters, I need to make a new API request to get the filtered set of data. Now if I try to change the filters rapidly, I'll end up making a ton of requests. Since those requests can come back in any order, things are going to get really weird really fast.

Here's an example of this issue in action.

%[https://www.loom.com/share/481708aa28f3407abc9c0dcb58076c14]

**Notice how rapidly clicking *Show Completed* updates the list multiple times. The list also ends up in the wrong state.**

## The Solution

So how do you fix the problem?

You can use an `AbortController`.

What the heck is an `AbortController`? Ok. I hear you. Let's take a step back and define a couple of terms:

### AbortController

[This is what MDN has to say about abort controllers](https://developer.mozilla.org/en-US/docs/Web/API/AbortController#:~:text=The%20AbortController%20interface%20represents%20a%20controller%20object%20that%20allows%20you%20to%20abort%20one%20or%20more%20Web%20requests%20as%20and%20when%20desired.):

> The AbortController interface represents a controller object that allows you to abort one or more Web requests as and when desired.

What does that mean for us?

Basically, the `AbortController` interface returns an object with these two properties:

- `signal` - an `AbortSignal`
- `abort` - a function to abort a request

### AbortSignal

Once again, [this is what MDN has to say about abort signals](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal#:~:text=The%20AbortSignal%20interface%20represents%20a%20signal%20object%20that%20allows%20you%20to%20communicate%20with%20a%20DOM%20request%20(such%20as%20a%20fetch%20request)%20and%20abort%20it%20if%20required%20via%20an%20AbortController%20object.):

> The AbortSignal interface represents a signal object that allows you to communicate with a DOM request (such as a fetch request) and abort it if required via an AbortController object.

The `AbortSignal` interface returns an object with these two properties:

- `aborted` - a boolean that tells you if the request was aborted
- `reason` - an optional message to explain why it was aborted

### Example

Let's take a look at a rough sketch at how you would use an `AbortController`:

```javascript
function getTheThing() {
  const controller = new AbortController();
  // `fetch` takes an optional `signal` property that it uses internally to cancel the request
  // If the request is canceled it will fall into the `catch`
  fetch('https://<appropriate_url>.com', { signal: controller.signal })
    .then(thing => console.log('THING: ', thing))
    .catch(err => console.log('ERROR: ', err));
  return controller;
}

const controller = getTheThing();

// Abort the request if it takes longer than a second
setTimeout(() => controller.abort('optional reason'), 1000);
```

The above example is ok, but it doesn't clearly show how `fetch` uses the `signal`. Things are abstracted away, so it's not obvious.

Here's another basic example so that you can get an idea about how to use things directly:

```javascript
function getTheThing() {
  const controller = new AbortController();
  setTimeout(() => {
    if (controller.signal.aborted) {
      console.log('We can check the signal to see if it was aborted');
    } else {
      console.log('Do something else if it wasn\'t aborted');
    }
  }, 2000);
}

const controller = getTheThing();

// Abort the request if it takes longer than a second
setTimeout(controller.abort, 1000);
```
**The above example might not be that useful, but you can clearly see how you can check the aborted status on the signal to change the code flow.**

How would this apply to the filter example from above? Well, all we'd need to do is just cancel the old request any time a new request is made. In other words, every time you change the filters for your list we cancel the previous request and make a new one.

Let's see how that looks.

%[https://www.loom.com/share/1211b8c22c664071850ed36abb83b0c3]

**Notice how this time the list doesn't update until I stop clicking. It also ends up in the correct state.**

## Demo

Try it out for yourself to see how things are working:

%[https://codesandbox.io/embed/loving-wildflower-y6p1ut?fontsize=14&hidenavigation=1&theme=dark]

## Conclusion

Sometimes the async code you write needs to be canceled.

It's no longer important to the user flow. The result of the `Promise` is unnecessary. `AbortSignal` can help make that process smoother by avoiding collisions in how the results are handled.

`AbortSignal` can help make sure the code you write is more predictable with less bugs.
