JavaScript Fetch API
The Fetch API provides a modern, promise-based way to make HTTP requests in JavaScript. It replaces the older XMLHttpRequest and provides a cleaner, more powerful interface for fetching resources across the network.
fetch() Basics
The fetch() function takes a URL as its first argument and returns a Promise that resolves to a Response object. The simplest use is a GET request to a URL.
// fetch() returns a Promise
// Simulating a fetch response
const mockResponse = {
ok: true,
status: 200,
json: () => Promise.resolve({ userId: 1, title: 'Hello' })
};
// In a real app:
// fetch('https://api.example.com/data')
// .then(response => response.json())
// .then(data => console.log(data));
// Simulated version:
Promise.resolve(mockResponse)
.then(function(response) {
console.log('Status: ' + response.status);
console.log('OK: ' + response.ok);
return response.json();
})
.then(function(data) {
console.log('Data: ' + JSON.stringify(data));
});GET and POST Requests
By default, fetch() makes a GET request. To make a POST request, pass an options object as the second argument with the method, headers, and body.
// GET request (default)
const getOptions = {
method: 'GET',
headers: {
'Accept': 'application/json'
}
};
console.log('GET options: ' + JSON.stringify(getOptions));
// POST request
const postData = { name: 'Alice', email: 'alice@example.com' };
const postOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
};
console.log('POST options: ' + JSON.stringify(postOptions));
console.log('POST body: ' + postOptions.body);Response Methods
The Response object has several methods to extract the body content: response.json() for JSON, response.text() for plain text, response.blob() for binary data, and response.formData() for form data.
| Method | Returns | Use Case |
|---|---|---|
| response.json() | Promise<Object> | Parse JSON response body |
| response.text() | Promise<String> | Get plain text response |
| response.blob() | Promise<Blob> | Binary data (images, files) |
| response.formData() | Promise<FormData> | Form data responses |
| response.arrayBuffer() | Promise<ArrayBuffer> | Raw binary buffer |
Headers
You can set and read HTTP headers using the Headers object or a plain object. Headers are used for content type negotiation, authentication, and other metadata.
// Creating headers with an object
const myHeaders = new Headers();
myHeaders.append('Content-Type', 'application/json');
myHeaders.append('Authorization', 'Bearer token123');
console.log('Content-Type: ' + myHeaders.get('Content-Type'));
console.log('Has Auth: ' + myHeaders.has('Authorization'));
// Headers can also be a plain object
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'myValue'
}
};
console.log('Method: ' + options.method);
console.log('Custom Header: ' + options.headers['X-Custom-Header']);Error Handling
Important: fetch() only rejects on network errors, not on HTTP error statuses like 404 or 500. You must check response.ok or response.status to handle HTTP errors.
async function safeFetch(url) {
try {
// Simulating fetch behavior
const response = { ok: false, status: 404, statusText: 'Not Found' };
if (!response.ok) {
throw new Error('HTTP Error: ' + response.status + ' ' + response.statusText);
}
return response;
} catch (error) {
console.log('Caught error: ' + error.message);
}
}
safeFetch('https://api.example.com/missing');
// Network error example
async function handleNetworkError() {
try {
throw new TypeError('Failed to fetch');
} catch (error) {
console.log('Network error: ' + error.message);
}
}
handleNetworkError();Async/Await with fetch
The Fetch API works seamlessly with async/await, making the code cleaner and easier to read than chaining .then() calls.
async function getUser(id) {
// Simulating an API call
const users = {
1: { id: 1, name: 'Alice', role: 'Admin' },
2: { id: 2, name: 'Bob', role: 'User' }
};
// In a real app: const response = await fetch(url);
const user = users[id];
if (!user) {
throw new Error('User not found');
}
return user;
}
async function main() {
try {
const user = await getUser(1);
console.log('Name: ' + user.name);
console.log('Role: ' + user.role);
const missing = await getUser(99);
} catch (error) {
console.log('Error: ' + error.message);
}
}
main();