JavaScript Essentials: Browser APIs - Fetch/HTTP
This document covers the Fetch API in JavaScript, a modern interface for making network requests. It's a replacement for the older XMLHttpRequest (XHR) object, offering a more powerful and flexible way to interact with web servers.
What is Fetch?
The Fetch API provides an interface for fetching resources (like data from a server). It's built on Promises, which makes asynchronous operations easier to handle. It allows you to:
- Make HTTP requests: GET, POST, PUT, DELETE, etc.
- Retrieve data: JSON, text, images, etc.
- Send data: Form data, JSON payloads, etc.
- Control request headers: Set authentication, content type, etc.
- Handle errors: Gracefully manage network issues and server errors.
Basic Fetch Usage
The core of the Fetch API is the fetch() function.
fetch('https://jsonplaceholder.typicode.com/todos/1') // Replace with your API endpoint
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json(); // Parse the response body as JSON
})
.then(data => {
console.log(data); // Process the JSON data
})
.catch(error => {
console.error('Fetch error:', error); // Handle any errors
});
Explanation:
fetch('https://jsonplaceholder.typicode.com/todos/1'): Initiates a GET request to the specified URL.fetch()returns a Promise..then(response => ...): This is the firstthenblock. It's executed when the request is successful (even if the HTTP status code is an error like 404). Theresponseobject contains information about the response, including headers, status code, and the response body.if (!response.ok): Checks if the HTTP status code indicates success (200-299). If not, it throws an error. This is crucial for handling server-side errors.return response.json(): Parses the response body as JSON. This also returns a Promise. Other methods include:response.text(): Parses the response body as text.response.blob(): Parses the response body as a Blob (for binary data like images).response.formData(): Parses the response body as FormData.response.arrayBuffer(): Parses the response body as an ArrayBuffer.
.then(data => ...): This secondthenblock is executed when the JSON parsing is complete. Thedatavariable contains the parsed JSON object..catch(error => ...): This block is executed if any error occurs during the fetch process (network error, invalid URL, JSON parsing error, or the error thrown in the firstthenblock).
Making Different Types of Requests
POST Request
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json' // Important for sending JSON data
},
body: JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1,
})
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log('Success:', data);
})
.catch(error => {
console.error('Error:', error);
});
Key points:
method: 'POST': Specifies the HTTP method.headers: An object containing request headers.Content-Typeis essential when sending data.body: The data to be sent in the request body.JSON.stringify()converts a JavaScript object into a JSON string.
PUT/DELETE Requests
Similar to POST, you specify the method and optionally include a body for PUT requests. DELETE requests typically don't have a body.
// PUT request
fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 1,
title: 'updated title',
body: 'updated body',
userId: 1,
})
})
.then(...) // Handle response
// DELETE request
fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'DELETE'
})
.then(...) // Handle response
Request Options
The second argument to fetch() is an options object. Here are some common options:
method: The HTTP method (GET, POST, PUT, DELETE, etc.). Defaults to 'GET'.headers: An object containing request headers.body: The request body (for POST, PUT, etc.).mode: Controls how the request is made (e.g.,cors,no-cors,same-origin).corsis the most common for cross-origin requests.credentials: Controls whether cookies, authorization headers, and TLS client certificates are sent with the request. Options:include,same-origin,omit.cache: Controls the caching behavior. Options:default,no-store,reload,no-cache,force-cache,only-if-cached.redirect: Controls how redirects are handled. Options:follow(default),error,manual.
Handling Errors
Proper error handling is crucial. The fetch() API doesn't automatically reject the Promise for HTTP error status codes (like 404 or 500). You must check response.ok and throw an error if it's false.
fetch('https://example.com/nonexistent-page')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.catch(error => {
console.error('Fetch error:', error);
});
Async/Await Syntax (Recommended)
Using async/await makes Fetch API code cleaner and more readable.
async function fetchData() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
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);
}
}
fetchData();
Explanation:
async function fetchData(): Declares an asynchronous function.await fetch(...): Pauses execution until thefetch()Promise resolves.await response.json(): Pauses execution until theresponse.json()Promise resolves.try...catch: Handles errors in a more structured way.
Resources
- MDN Web Docs - Fetch API: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
- JSONPlaceholder (for testing): https://jsonplaceholder.typicode.com/
This provides a solid foundation for using the Fetch API in JavaScript. Remember to always handle errors and choose the appropriate request method and options for your specific needs. Using async/await is highly recommended for cleaner and more maintainable code.