Master Code
On The Go

Learn. Practice. Build.

Home › Code Snippets › JavaScript Snippets › AbortController

JavaScript Snippet

JavaScript AbortController

Cancel fetch requests, implement timeouts, and prevent race conditions — with an interactive live demo.

Last updated: October 2026

Quick answer: Create an AbortController, pass its signal to fetch, and call controller.abort() to cancel. The fetch promise rejects with an AbortError — always check err.name === 'AbortError' to distinguish cancellations from real errors. Use AbortSignal.timeout(ms) for automatic timeouts [citation:5][citation:7][citation:11].

🎬 Interactive Live Demo

Click "Start Request" and then "Cancel" to see AbortController in action. Watch the status log.

💡 The request hits a real 2-second delayed endpoint. Click Cancel to abort it mid-flight and see the AbortError in action.

1

The Basic Pattern

Create an AbortController, pass its signal to fetch, and call abort() when you need to cancel:

const controller = new AbortController();

fetch('/api/data', { signal: controller.signal })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(err => {
        if (err.name === 'AbortError') {
            console.log('Request was cancelled');
        } else {
            console.error('Real error:', err);
        }
    });

// Cancel the request
controller.abort();

When abort() is called, the fetch promise rejects with a DOMException named AbortError — not a network error [citation:7][citation:11].

2

Why AbortController Matters

Without cancellation, every request continues to completion — wasting bandwidth, CPU, and memory. Three common problems this solves:

  • Race conditions: If a user types "React" then quickly "Vue", the "React" response might arrive after "Vue" and overwrite the correct results [citation:29].
  • Memory leaks: If a component unmounts while a request is in flight, setting state on the unmounted component triggers warnings and leaks [citation:25].
  • Wasted resources: A slow request the user no longer needs still consumes network bandwidth and server resources [citation:5].
3

Real-World Use Case: Search Autocomplete

The classic pattern — cancel the previous request before starting a new one:

let controller = null;

async function search(query) {
    // Cancel the previous request if it exists
    if (controller) controller.abort();

    // Create a new controller for this request
    controller = new AbortController();

    try {
        const response = await fetch(`/api/search?q=${query}`, {
            signal: controller.signal
        });
        const results = await response.json();
        renderResults(results);
    } catch (err) {
        if (err.name === 'AbortError') return; // Expected — ignore
        showError(err);
    }
}

Note: you must create a new controller for each request. Once aborted, a signal cannot be un-aborted [citation:29].

4

Implementing Timeouts

Modern browsers support AbortSignal.timeout(ms) for automatic cancellation after a delay [citation:7][citation:38]:

try {
    const response = await fetch('/api/slow', {
        signal: AbortSignal.timeout(5000)  // Cancel after 5s
    });
    const data = await response.json();
} catch (err) {
    if (err.name === 'TimeoutError') {
        console.error('Request timed out');
    } else {
        console.error('Other error:', err);
    }
}

Important: Timeouts throw TimeoutError, not AbortError. These are different and must be handled separately [citation:7][citation:25].

💡 Combining signals: Use AbortSignal.any([controller.signal, AbortSignal.timeout(5000)]) to cancel on either a manual abort or a timeout [citation:7][citation:38].

5

Cleanup in React (useEffect)

In React, always abort on cleanup to prevent state updates on unmounted components [citation:25]:

useEffect(() => {
    const controller = new AbortController();

    fetch(`/api/user/${userId}`, { signal: controller.signal })
        .then(res => res.json())
        .then(setUser)
        .catch(err => {
            if (err.name !== 'AbortError') setError(err);
        });

    return () => controller.abort();
}, [userId]);

When userId changes or the component unmounts, the previous request is cancelled automatically. This is the recommended pattern in React documentation [citation:25][citation:29].

🎯 AbortError vs TimeoutError vs Network Error

Error Cause Should you show the user?
AbortError Manual abort() call No — silent
TimeoutError AbortSignal.timeout() Maybe — depends on UX
TypeError Network failure Yes — real error

Always check err.name before displaying errors. An AbortError is not a bug — it's expected behavior [citation:2][citation:17].

⚠️ Common Mistakes

❓ Frequently Asked Questions

What is AbortController in JavaScript?

AbortController is a Web API that lets you cancel asynchronous operations like fetch requests. You create a controller, pass its signal to fetch, and call controller.abort() to cancel the request. This prevents unnecessary network usage, avoids race conditions, and improves performance.

How do I cancel a fetch request?

Create an AbortController instance, pass its signal property to the fetch options object, and call controller.abort() when you want to cancel. The fetch promise will reject with an AbortError that you can catch and handle.

What is the difference between AbortController and AbortSignal?

AbortController is the object that lets you abort operations. AbortSignal is the object that gets passed to the operation (like fetch) and carries the abort status. The controller has the abort() method; the signal is what listens for the abort event.

How do I set a timeout on a fetch request?

Use AbortSignal.timeout(ms) to automatically abort the request after a specified number of milliseconds. The fetch will reject with a TimeoutError. For custom timeouts or combining with manual abort, use AbortSignal.any() to merge signals.

Why am I getting an AbortError?

An AbortError means the request was cancelled via AbortController.abort() or a timeout occurred. This is not a bug — it is expected behavior. Always check err.name === 'AbortError' in your catch block to distinguish cancellations from real network errors.

🎯 What's Next?

← All JavaScript Snippets