AJAX Interview Questions

Commonly asked AJAX and fetch() interview questions with clear, practical answers.

Common AJAX and fetch() interview questions — the kind that come up in front-end and full-stack screens.

Q: What is AJAX, and does it actually require XML? AJAX stands for Asynchronous JavaScript And XML, but the name is a historical artifact from when it was coined in 2005. In practice, modern AJAX requests use JSON almost exclusively — JSON is more compact and maps directly onto JavaScript objects. AJAX today really just means "use JavaScript to make an asynchronous HTTP request and update the page without a full reload."

Q: What's the difference between XMLHttpRequest and the fetch() API? fetch() is promise-based, so it composes cleanly with .then() chains and async/await. XMLHttpRequest is older and event/callback-based (onload, onerror, onprogress), requiring more manual setup — creating an object, wiring handlers, and manually checking the status code. Nearly all new code uses fetch(); XMLHttpRequest mainly survives in legacy codebases and in a few libraries that still rely on its fine-grained upload progress events.

Q: Why doesn't fetch() throw an error for a 404 or 500 response? fetch()'s promise only rejects for network-level failures — the request couldn't reach a server at all, was blocked (e.g., by CORS), or a similar transport-level issue. An HTTP response with an error status code (404, 500, etc.) is still a completed, "successful" exchange from fetch()'s point of view. You have to explicitly check response.ok (true for 200–299) or response.status and throw your own error when the request wasn't actually successful.

Q: What is the same-origin policy, and how does CORS relate to it? The same-origin policy is a browser security rule that, by default, blocks JavaScript running on one origin (scheme + host + port) from reading responses from a different origin. CORS (Cross-Origin Resource Sharing) is the mechanism that relaxes this restriction in a controlled way: the server being called sends back headers like Access-Control-Allow-Origin explicitly permitting certain origins to read its responses. Without the right CORS headers, the browser blocks the JavaScript from reading the response even if the request itself reached the server successfully.

Q: When would you prefer .then() chains over async/await, or vice versa? They're functionally equivalent — async/await is syntax sugar over the same promise mechanics. Most teams default to async/await because it reads top-to-bottom like synchronous code and lets you handle errors with a single try/catch instead of a .catch() at the end of a chain. .then() chains still show up naturally for very short, single-step transformations, or in codebases/style guides that predate widespread async/await adoption.

Q: What's the safest way to retry a failed AJAX request without making things worse? Only retry requests that are safe to repeat — GET, and idempotent methods generally — and back off exponentially between attempts (roughly doubling the delay each time, with a little random jitter added) rather than retrying immediately or at a fixed interval. Retrying immediately at a fixed pace risks a "thundering herd," where many clients failing at once all retry in lockstep and pile even more load onto an already struggling server; jitter spreads those retries out.

Q: Why doesn't fetch() have a built-in timeout option? The Fetch spec left timeouts to be composed from existing primitives rather than adding a dedicated option — AbortController (or the newer AbortSignal.timeout(ms) shortcut) cancels a request after a set duration by aborting its signal, which makes the fetch() promise reject with an AbortError. This reuses the same cancellation mechanism used for other reasons to abort a request (like a new keystroke canceling a stale search) instead of needing a separate, special-cased timeout feature.

Q: Is it ever wrong to retry a POST request? Yes, unless the operation is genuinely idempotent or protected by something like an idempotency key. A POST that creates a resource or charges a payment can have already succeeded server-side even though the client never received the response (a lost response, not a lost request) — blindly retrying it risks creating a duplicate resource or a duplicate charge, a categorically worse outcome than just failing once.

Q: What's the difference between CORS and the same-origin policy? The same-origin policy is the browser's default, restrictive behavior: JavaScript on one origin cannot read a response from a different origin. CORS is the mechanism a server uses to deliberately relax that default for specific origins, by sending headers like Access-Control-Allow-Origin — it's an opt-in exception process, not a separate security feature layered on top; without the right CORS headers from the server, the same-origin policy's default restriction simply stays in effect.

Q: When would you reach for Server-Sent Events instead of building a feature on WebSockets? When the data only ever needs to flow one way, from server to client — SSE gives you a persistent connection over plain HTTP with automatic reconnection built into the browser's EventSource API, for less complexity than a full bidirectional WebSocket. WebSockets earn their extra complexity specifically when the client also needs to send frequent messages back over that same live connection, not just receive updates.