DEV3 Technologies home

DEV3 Developer Forum

How do I cancel a fetch request or add a timeout in JavaScript?

JavaScript helpSolved0 views
dev3 ·

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

0

1 reply

dev3 · Accepted answer

Use AbortController. Pass its signal to fetch; calling abort() rejects the promise with an AbortError.

Cancel previous request (search as you type)

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;
  }
}

Timeout

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).

Combine user cancel and timeout

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.

React effect cleanup

useEffect(() => {
  const c = new AbortController();
  fetch(url, { signal: c.signal }).then(r => r.json()).then(setData).catch(() => {});
  return () => c.abort();
}, [url]);

Notes

  • Aborting stops waiting and closes the connection from the client; the server may still finish processing.
  • A signal can be reused across several fetches to cancel them together, but once aborted it stays aborted.

Pitfall: not catching AbortError produces noisy unhandled rejections when users navigate away.

0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.