XMLHttpRequest vs Fetch vs Axios
Making HTTP requests in the browser is a fundamental part of web development. For a long time, we had one primary tool for this: XMLHttpRequest. Then came the Fetch API, a more modern and flexible approach. And more recently, libraries like Axios have gained huge popularity. Let’s break down what each one offers and when you might choose one over the others.
XMLHttpRequest (XHR)
This is the old guard. XMLHttpRequest has been around since Internet Explorer 5. It’s built right into the browser, so no external libraries are needed. It’s powerful, but its API can feel a bit clunky and low-level by today’s standards.
Here’s a basic GET request using XHR:
const xhr = new XMLHttpRequest();xhr.open('GET', '/api/data', true);
xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300) { console.log(xhr.responseText); } else { console.error('Request failed:', xhr.statusText); }};
xhr.onerror = function() { console.error('Network error occurred');};
xhr.send();Notice the callback-based approach for success and error handling. It’s very event-driven. While it works, it can lead to callback hell if you’re making multiple sequential requests.
Fetch API
The Fetch API is a modern interface for fetching resources. It’s Promise-based, which makes asynchronous code much cleaner and easier to manage. It’s also more powerful and flexible than XHR. You can control request headers, methods, body, caching, and more with ease.
Here’s the equivalent GET request using Fetch:
fetch('/api/data') .then(response => { if (!response.ok) { throw new Error('Network response was not ok ' + response.statusText); } return response.json(); // or response.text(), etc. }) .then(data => { console.log(data); }) .catch(error => { console.error('There has been a problem with your fetch operation:', error); });Using Promises with async/await makes it even cleaner:
async function fetchData() { try { const response = await fetch('/api/data'); if (!response.ok) { throw new Error('Network response was not ok ' + response.statusText); } const data = await response.json(); console.log(data); } catch (error) { console.error('There has been a problem with your fetch operation:', error); }}
fetchData();Fetch handles JSON parsing nicely and has built-in support for various request options.
Axios
Axios is a popular, Promise-based HTTP client for the browser and Node.js. It’s not built into the browser, so you need to include it as a dependency. What makes Axios stand out are its convenience features and broad browser compatibility.
Key features include:
- Automatic JSON data transformation.
- Request and response interceptors (great for adding auth tokens, logging, etc.).
- Client-side protection against XSRF.
- Cancellation of requests.
- Better error handling out of the box.
Here’s the Axios version:
// Assuming axios is imported: import axios from 'axios';
axios.get('/api/data') .then(response => { console.log(response.data); }) .catch(error => { console.error('Error fetching data:', error); });And with async/await:
async function fetchData() { try { const response = await axios.get('/api/data'); console.log(response.data); } catch (error) { console.error('Error fetching data:', error); }}
fetchData();Axios automatically parses JSON, and its error object often contains more useful information than native Fetch or XHR errors.
Which One To Use?
-
XMLHttpRequest: If you need to support very old browsers or have a legacy codebase that heavily relies on it. For new projects, it’s generally not recommended.
-
Fetch API: This is the modern, native browser API. It’s excellent for most use cases, especially if you want to avoid external dependencies. It’s powerful and becoming the standard. However, it doesn’t automatically transform JSON responses, and error handling for non-2xx status codes requires explicit checks.
-
Axios: If you need features like interceptors, request cancellation, better error handling out of the box, or guaranteed browser compatibility across a wide range. It’s a fantastic choice for many applications, especially if you’re comfortable adding an external dependency. It often feels more complete for complex API interactions.
For new projects, I typically lean towards Fetch for its native capabilities and simplicity, or Axios if the project complexity warrants its advanced features. Both are solid choices, and understanding their differences helps you pick the right tool for the job.