How do you stop a fetch request from waiting forever when the server never answers?
Pass signal: AbortSignal.timeout(ms) in the fetch options — after that many milliseconds the request is aborted and the await throws a catchable error.
* The signal turns "waiting forever" into a second, catchable exit path. *
fetch() has no built-in timeout: if the server accepts the connection but never responds, the Promise simply stays pending and your UI waits forever. The fix is the abort mechanism:
try {
const response = await fetch('/api/data', {
// Give up after 5 seconds
signal: AbortSignal.timeout(5000)
});
// ... handle response
} catch (error) {
// Network failure OR timeout both land here
}
AbortSignal.timeout(5000) creates a signal that fires after 5000 ms; when it fires, the browser cancels the request and the await fetch(...) rejects with a TimeoutError — landing in your catch block exactly like a network failure. That turns "the page silently hangs" into an error path you can show to the user, which is why it belongs in every fetch that talks to a backend.
Go deeper:
MDN: AbortSignal.timeout() — the reference, including the
TimeoutErrorit rejects with.