AJAX - Timeouts in AJAX
1) Why Do We Need Timeouts?
-
Sometimes the server takes too long (heavy query, poor connection).
-
Without a timeout, the request can hang forever, blocking user feedback.
-
Timeout handling allows you to cancel the request and inform the user (e.g., “Server is taking too long, please try again”).
2) Timeout with XMLHttpRequest
XMLHttpRequest has a built-in .timeout property and .ontimeout event.
const xhr = new XMLHttpRequest();
xhr.open("GET", "/api/slow", true);
// set timeout in milliseconds (e.g., 5 seconds)
xhr.timeout = 5000;
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
console.log("Response:", xhr.responseText);
} else {
console.error("HTTP Error:", xhr.status);
}
};
xhr.ontimeout = () => {
console.error("Request timed out after 5 seconds");
};
xhr.onerror = () => {
console.error("Network error");
};
xhr.send();
3) Timeout with fetch()
fetch() does not have a built-in timeout.
Instead, you use AbortController + setTimeout.
const controller = new AbortController();
const signal = controller.signal;
// set timeout (e.g., 5 seconds)
const timeoutId = setTimeout(() => controller.abort(), 5000);
fetch("/api/slow", { signal })
.then(res => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
})
.then(data => console.log("Data:", data))
.catch(err => {
if (err.name === "AbortError") {
console.error("Request aborted (timeout)");
} else {
console.error("Fetch error:", err.message);
}
})
.finally(() => clearTimeout(timeoutId));
4) Timeout Strategies
-
Hard timeout: Always cancel if server exceeds a fixed time (e.g., 10 seconds).
-
Adaptive timeout: Adjust based on network conditions (shorter on fast WiFi, longer on mobile).
-
Progressive retry with backoff: Retry after failure, wait longer each time (1s → 2s → 4s).
5) Best Practices
-
Pick a reasonable timeout:
-
API calls → 5–10 seconds.
-
File uploads/downloads → much longer (depends on file size).
-
-
Inform the user:
-
Show a loading indicator while waiting.
-
Replace with “Taking too long, retry?” if timeout occurs.
-
-
Don’t retry blindly — use backoff to avoid hammering the server.
-
Abort unnecessary requests: If a user navigates away or triggers a new request, cancel the old one to save bandwidth.
Summary:
-
XMLHttpRequest→ use.timeout+.ontimeout. -
fetch→ useAbortController+setTimeout. -
Always show user-friendly feedback when a request is too slow.