Code Snippets
/

Cancellable fetch with AbortController

Cancellable fetch with AbortController

Every modern UI eventually needs to cancel in-flight requests: a search box that fires on every keystroke, a route change that abandons a partially loaded page, a tab close that should free sockets. `AbortController` is the standard primitive for this. This snippet covers the minimal abort pattern, a `fetchWithTimeout` helper that aborts on a deadline, and a hook-friendly cleanup pattern that pairs each request with its own controller.

JavaScript
Medium
3 snippets
async-programming
js-fetch-api
utility
error-handling

1,059 views

6

// In real code: const res = await fetch(url, { signal: ac.signal });
// We simulate fetch here so the snippet runs offline.
function fakeFetch(url, { signal } = {}) {
    return new Promise((resolve, reject) => {
        const id = setTimeout(() => resolve({ ok: true, url }), 200);
        if (signal) {
            signal.addEventListener('abort', () => {
                clearTimeout(id);
                reject(new DOMException('Aborted', 'AbortError'));
            }, { once: true });
        }
    });
}

const ac = new AbortController();
fakeFetch('/api/users', { signal: ac.signal })
    .then((r) => console.log('done', r.url))
    .catch((err) => console.log('err:', err.name));

// Caller cancels almost immediately.
setTimeout(() => ac.abort(), 10);

An AbortController exposes a .signal you pass into any abort-aware async API and an .abort() method that flips the signal. When abort() fires, fetch (or your fake fetch) rejects with a DOMException whose name is 'AbortError', which lets callers tell user-cancelled work apart from real failures. Always store the controller alongside the request so a follow-up handler can reach it (route change, search input, component unmount). Once aborted, a controller cannot be reused; create a fresh one per request.