I want to cancel an in-flight fetch when the user types a new search term, and also time out after 8 seconds. What is the modern way?
#javascript#fetch#abortcontroller
DEV3 Developer Forum
Every post is reviewed first. Usually reviewed within 24 hours.
I want to cancel an in-flight fetch when the user types a new search term, and also time out after 8 seconds. What is the modern way?
#javascript#fetch#abortcontroller
Use AbortController. Pass its signal to fetch; calling abort() rejects the promise with an AbortError.
let controller;
async function search(q) {
controller?.abort();
controller = new AbortController();
try {
const res = await fetch(`/api/search?q=${encodeURIComponent(q)}`, {
signal: controller.signal,
});
return await res.json();
} catch (err) {
if (err.name === 'AbortError') return null; // expected, ignore
throw err;
}
}
Modern browsers and Node 18+ support AbortSignal.timeout:
const res = await fetch(url, { signal: AbortSignal.timeout(8000) });
It rejects with a TimeoutError (name TimeoutError, not AbortError).
const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(8000)]);
AbortSignal.any is available in current evergreen browsers and recent Node releases; otherwise create a manual setTimeout(() => controller.abort(), 8000) and clearTimeout it in finally.
useEffect(() => {
const c = new AbortController();
fetch(url, { signal: c.signal }).then(r => r.json()).then(setData).catch(() => {});
return () => c.abort();
}, [url]);
Pitfall: not catching AbortError produces noisy unhandled rejections when users navigate away.