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

  1. Pick a reasonable timeout:

    • API calls → 5–10 seconds.

    • File uploads/downloads → much longer (depends on file size).

  2. Inform the user:

    • Show a loading indicator while waiting.

    • Replace with “Taking too long, retry?” if timeout occurs.

  3. Don’t retry blindly — use backoff to avoid hammering the server.

  4. 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 → use AbortController + setTimeout.

  • Always show user-friendly feedback when a request is too slow.