AbortController in JavaScript and React — Explained for Beginners


Have you ever started something and then realized you didn’t need to finish it? Maybe you ordered a pizza but changed your mind and made maggi instead. Wouldn’t it be nice if you could call the delivery guy and say:
“Stop! I don’t need that pizza anymore.”
That’s exactly what AbortController
does in JavaScript.
AbortController
lets you stop async operations you no longer need - usually used for network requests but can also be used for file operations, DOM event listeners, timers, streaming operations, and custom async tasks - saving time, memory, and avoiding messy bugs.
What is AbortController?
AbortController
is a built-in browser API that gives you control over asynchronous operations — mainly network requests using fetch()
.
It has two parts:
controller — the “remote control”
signal — the “wire” that connects your request to the controller
When you call controller.abort()
, any request linked to its signal
will immediately stop. ( Don’t worry we will dive deep into this soon ! )
Why do we need it?
Before AbortController
, once you started a fetch request:
You had to wait until it finished — even if you didn’t need the result anymore.
If you tried to update your app after the component disappeared (like in React), you could get warnings like:
“Can't perform a React state update on an unmounted component.”
This caused:
Memory leaks — unused requests still running
Race conditions — slow responses overwriting newer ones
Annoying errors — because your code tried to update something that no longer exists
How Does It Work?
Basic Example in JavaScript
const controller = new AbortController(); // 1. Create controller
const signal = controller.signal; // 2. Get signal
fetch("https://jsonplaceholder.typicode.com/posts", { signal })
.then(res => res.json())
.then(data => console.log(data))
.catch(err => {
if (err.name === "AbortError") {
console.log("Request was aborted!");
} else {
console.error("Fetch failed:", err);
}
});
// Later (maybe user navigated away)
controller.abort(); // Stop the request
- When you call
abort()
, the fetch stops immediately and throws anAbortError
.
Using AbortController in React
React components mount and unmount as users navigate around.
If a fetch is still running after a component unmounts, React may try to update state that no longer exists.
To avoid this, cancel your requests inside a cleanup function using AbortController
.
import { useEffect, useState } from "react";
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const controller = new AbortController();
fetch("https://jsonplaceholder.typicode.com/users", { signal: controller.signal })
.then(res => res.json())
.then(data => {
setUsers(data);
setLoading(false);
})
.catch(err => {
if (err.name === "AbortError") {
console.log("Fetch aborted");
}
});
return () => controller.abort(); // Cancel when component unmounts
}, []);
if (loading) return <p>Loading...</p>;
return (
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
Modern Real-World Uses
1. Cancel Old Searches When New Ones Start
Perfect for search bars or autocomplete:
let controller;
async function search(query) {
if (controller) controller.abort(); // Cancel previous request
controller = new AbortController();
try {
const res = await fetch(`/api/search?q=${query}`, { signal: controller.signal });
const data = await res.json();
console.log("Results:", data);
} catch (err) {
if (err.name === "AbortError") console.log("Old search aborted");
}
}
2. Cancel Multiple Requests Together
const controller = new AbortController();
Promise.all([
fetch('/api/1', { signal: controller.signal }),
fetch('/api/2', { signal: controller.signal })
])
.catch(err => {
if (err.name === 'AbortError') console.log('Both requests aborted');
});
controller.abort(); // Cancels all at once
AbortController with Axios
Old Way (Before Axios v0.22)
Axios had a custom CancelToken
API.
Modern Way (Axios v0.22+)
Axios now supports AbortController natively:
const controller = new AbortController();
axios.get('/user', { signal: controller.signal })
.then(res => console.log(res.data))
.catch(err => {
if (err.code === 'ERR_CANCELED') console.log('Request canceled!');
});
// Cancel the request when needed
controller.abort();
This matches the browser standard and works just like fetch.
Key Takeaways
What it is: A remote control to stop async operations like fetch.
Why it matters: Prevents wasted work, race conditions, and React warnings.
How to use it: Create a controller → pass
signal
to your request → callabort()
when done.Modern support: Native in fetch, supported in Axios and most libraries.
Final Analogy to Remember
Think of AbortController
as a remote control for network requests:
You plug in the “wire” (signal) into your request.
If you no longer need that request — maybe you switched pages or started a new search —
You press STOP (
controller.abort()
), and the request vanishes instantly.
No more cold pizza deliveries you didn’t ask for! 🍕
In short:
AbortController = less wasted work, fewer bugs, happier apps.
Subscribe to my newsletter
Read articles from Yash Grover directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
