XMLHttpRequest vs Fetch API: Key Differences
This article provides a direct comparison between JavaScript’s
traditional XMLHttpRequest object and the modern
Fetch API. Both mechanisms enable asynchronous HTTP
requests in web applications, allowing data retrieval without full page
reloads. While XMLHttpRequest uses an older callback-driven
model, the Fetch API introduces a modern, Promise-based
interface that simplifies network handling, improves readability, and
integrates seamlessly with modern JavaScript features like
async/await.
1. Programming Model: Callbacks vs. Promises
- XMLHttpRequest (XHR): Relies on event listeners and
callback functions to track the state of a request. Developers must
attach listeners to events like
onload,onerror, oronreadystatechange. - Fetch API: Built natively on JavaScript Promises.
This eliminates “callback hell” and allows chaining using
.then()and.catch(), or using cleanasync/awaitsyntax.
2. Syntax Comparison
Making a GET Request with XMLHttpRequest:
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
const data = JSON.parse(xhr.responseText);
console.log(data);
} else {
console.error('Request failed with status:', xhr.status);
}
};
xhr.onerror = function () {
console.error('Network error occurred');
};
xhr.send();Making a GET Request with Fetch API:
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Fetch error:', error.message);
}
}
fetchData();3. HTTP Error Handling
- XMLHttpRequest: Treats non-2xx status codes (such
as
404 Not Foundor500 Internal Server Error) as successful network transactions, requiring manual status code checks inonload. - Fetch API: Also resolves the Promise on HTTP error
status codes (like 404 or 500). A Fetch Promise only rejects on complete
network failures or if the request is aborted. To check for successful
responses, you must verify the
response.okboolean property.
4. Progress Tracking and File Uploads
- XMLHttpRequest: Features native, built-in support
for monitoring upload and download progress via the
xhr.upload.onprogressandxhr.onprogressevents. - Fetch API: Supports download progress tracking
through the
ReadableStreaminterface (response.body.getReader()), but does not have a straightforward, native mechanism for tracking upload progress.
5. Request Cancellation
- XMLHttpRequest: Has a dedicated method,
xhr.abort(), which immediately cancels the in-flight request. - Fetch API: Uses the standard
AbortControllerinterface. You pass anAbortSignalto the fetch options and callcontroller.abort()to terminate the request.
6. Cookies and Credentials
- XMLHttpRequest: Automatically sends same-origin cookies and authentication headers by default.
- Fetch API: Controls credentials via the
credentialsproperty ('omit','same-origin', or'include'). While modern implementations default to'same-origin', explicit configuration is required when dealing with cross-origin credentials.
Summary Comparison
| Feature | XMLHttpRequest | Fetch API |
|---|---|---|
| Architecture | Event/Callback-based | Promise-based
(async/await) |
| Data Parsing | Manual (JSON.parse) |
Built-in methods (.json(),
.text(), .blob()) |
| Request Abort | xhr.abort() |
AbortController /
AbortSignal |
| Upload Progress | Native onprogress
support |
Complex (Requires Streams) |
| Standardization | Legacy standard | Modern Web standard |