Fetch API
Comprehensive guide to using the Fetch API in JavaScript for making HTTP requests, handling responses, and managing errors.
Fetch API
The Fetch API provides a modern, promise-based way to make HTTP requests in JavaScript. It simplifies the process of sending requests to and receiving responses from web servers compared to older technologies like XMLHttpRequest.
What is Fetch API?
The Fetch API is built into modern browsers and provides an interface for accessing and manipulating HTTP requests and responses.
fetch(url, options)url: The resource URL.options(optional): An object to customize the request (method, headers, body, etc.).
The fetch() function returns a Promise that resolves to a Response object.
Basic GET Request
A simple use case is fetching data from a public API.
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Fetch error:', error);
});Explanation
fetch()initiates the HTTP request.- The first
.then()checks if the response was successful (response.ok). .json()parses the response body into a JavaScript object.- The final
.catch()handles network errors or parsing issues.
Sending POST Requests
For sending data to the server, configure the method, headers, and body in the options object.
fetch('https://api.example.com/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'John Doe', age: 30 }),
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));Key Points
- Use
method: 'POST'for POST requests. headersspecify the data format.bodycarries the payload, usually stringified JSON.
Working with Response Headers
The Response object provides access to headers.
fetch('https://api.example.com/data')
.then(response => {
console.log('Content-Type:', response.headers.get('Content-Type'));
return response.json();
})
.then(data => console.log(data));Handling Errors
The Fetch API does not reject the Promise for HTTP error statuses (like 404 or 500). It only rejects on network errors.
fetch('https://api.example.com/invalid-endpoint')
.then(response => {
if (!response.ok) {
throw new Error(`Server responded with ${response.status}`);
}
return response.json();
})
.catch(error => console.error('Fetch failed:', error));Always check response.ok and response.status.
Aborting a Fetch Request
Use the AbortController to cancel fetch requests.
const controller = new AbortController();
const signal = controller.signal;
fetch('https://api.example.com/data', { signal })
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Fetch aborted');
} else {
console.error('Fetch error:', error);
}
});
// Abort after 3 seconds
setTimeout(() => controller.abort(), 3000);Timeout Implementation
Fetch has no built-in timeout, so combine it with AbortController for timeouts.
function fetchWithTimeout(url, options, timeout = 5000) {
const controller = new AbortController();
const signal = controller.signal;
const fetchPromise = fetch(url, { ...options, signal });
const timeoutId = setTimeout(() => controller.abort(), timeout);
return fetchPromise
.finally(() => clearTimeout(timeoutId));
}
fetchWithTimeout('https://api.example.com/data', {}, 3000)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Request timed out');
} else {
console.error('Fetch error:', error);
}
});Streaming Response Body
Access the response body as a stream using response.body.
fetch('https://api.example.com/large-file')
.then(response => {
const reader = response.body.getReader();
return new ReadableStream({
start(controller) {
function push() {
reader.read().then(({ done, value }) => {
if (done) {
controller.close();
return;
}
controller.enqueue(value);
push();
});
}
push();
}
});
})
.then(stream => {
// Process the stream
console.log('Stream is ready');
});Best Practices
- Always handle
response.okto catch HTTP errors. - Use
AbortControllerfor cancellations and timeouts. - Keep headers explicit for content type.
- For large responses, prefer streaming over buffering the entire payload in memory.