Fetch API
The Fetch API provides a modern, versatile interface for fetching resources (including across the network). It is a cleaner, Promise-based alternative to the older XMLHttpRequest (XHR).
1. Basic GET Request
By default, fetch() makes a GET request. It returns a Promise that resolves to the Response object representing the response to the request.
fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => {
// Check if the response was successful (status 200-299)
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// Parse the JSON body
return response.json();
})
.then(data => {
console.log('User data:', data);
})
.catch(error => {
console.error('Fetch error:', error);
});
2. Using Async/Await
async/await syntax makes fetch calls much easier to read, looking almost like synchronous code.
async function getUser(id) {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data;
} catch (error) {
console.error('Failed to fetch user:', error);
}
}
3. Making POST, PUT, and DELETE Requests
To make requests other than GET, you pass an optional init object as the second argument to fetch.
POST Request (Creating data)
async function createUser(userData) {
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN_HERE'
},
body: JSON.stringify(userData) // Data must be stringified!
});
return response.json();
}
PUT Request (Updating data)
const response = await fetch('https://jsonplaceholder.typicode.com/users/1', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Jane Doe' })
});
DELETE Request (Removing data)
const response = await fetch('https://jsonplaceholder.typicode.com/users/1', {
method: 'DELETE'
});
// Usually returns 200 OK or 204 No Content
4. Important Error Handling Nuance
A fetch() promise only rejects when a network error occurs (e.g., DNS lookup failure, no internet connection). It does NOT reject on HTTP errors (like 404 or 500).
You must manually check the response.ok property (which is true for status codes 200-299) and throw an error if necessary.
const response = await fetch('/api/data');
// Even if status is 404 or 500, fetch will RESOLVE the promise
if (!response.ok) {
throw new Error(`HTTP Error: ${response.status}`);
}
5. Canceling a Fetch Request (AbortController)
Sometimes you need to cancel an ongoing fetch request (e.g., the user navigated away from the page, or typed a new search query). You can do this using the AbortController API.
// 1. Create the controller
const controller = new AbortController();
const signal = controller.signal;
async function fetchData() {
try {
// 2. Pass the signal to fetch
const response = await fetch('https://api.example.com/huge-data', { signal });
const data = await response.json();
console.log(data);
} catch (error) {
// 3. Handle the abort error
if (error.name === 'AbortError') {
console.log('Fetch successfully canceled');
} else {
console.error('Fetch error:', error);
}
}
}
fetchData();
// 4. Call abort() when you want to cancel
setTimeout(() => {
controller.abort();
}, 1000); // Cancels the request if it takes longer than 1 second