API calls are the core of any application today. For the longest though, properly managing your API calls took some custom implementation. Realistically, that is always going to be a mess unless a lot of time is invested into perfecting it. Luckily though, there is an interface available to make this easier in JavaScript. AbortController.
AbortController allows us to have some control over when, and what conditions should trigger the cancellation of API request(s). This is a great tool to have an understanding of regardless of what framework, or lack thereof, you’re working with. So let’s dive in!
What Is AbortController
As mentioned prior, the AbortController is an object instance that can be used to better handle abruptly stopping API calls before they finish. This interface is readily available in modern browsers, and a polyfill is available if needed for additional support. Usage is straightforward as well, only three things are needed to be used with it.
Creating a new instance with const controller = new AbortController();
, accessing and passing the signal in your new controller, controller.signal
, and signaling to stop your request with .abort()
; It’s really that easy!
Full Usage
Now using AbortController is fully dependent on the framework choice, or lack thereof. To get going, we’ll look into using it with Vanilla JS.
let controller: AbortController;
const abortImageRequest = () => {
if (controller) {
controller.abort();
}
};
const fetchPicture = async () => {
try {
controller = new AbortController();
const signal = controller.signal;
signal.addEventListener('abort', () => window.alert('API call aborted'));
const response = await fetch(
'https://picsum.photos/200/300',
{ signal }
);
console.log("Image URL: ", response.url);
} catch(error) {
console.error(error);
throw new Error(error);
}
}
As you can see above, using Vanilla JS(Typescript) is pretty simple. We can even add event listeners to our signal variable for allowing callback functions to be called when an abort happens. Let’s now take a look at a common use case in the React world!
import { useEffect } from "react";
const TestComponent = () => {
useEffect(() => {
const controller: AbortController = new AbortController();
const signal = controller.signal;
const fetchImage = async () => {
try {
const response = await fetch(
'https://picsum.photos/200/300',
{ signal }
);
console.log("Image URL: ", response.url);
} catch(error) {
console.error(error);
}
};
fetchImage();
return () => {
controller.abort();
}
}, []);
}
export default TestComponent;
In the React component above, we’re using our AbortController
to ensure that in the event the component is unmounted that the API request is successfully stopped. That way we don’t have to worry about the API request continuing to run after the fact.
In Closing
When I stumbled upon this interface I was so relieved. Prior to this, it was a pretty gruesome manual job to be able to have something like this. So take advantage of this, and clean up your application’s performance!