Skip to content

ajax_fetch_request

The fetch() API is the modern, promise-based standard for making asynchronous HTTP requests in the browser (and other environments like Node.js). It replaces the older XMLHttpRequest object with a cleaner and more powerful interface.

The simplest use of fetch() takes one argument: the URL of the resource you want to fetch. By default, it makes a GET request.

fetch() returns a Promise that resolves to the Response to that request, whether it is successful or not. You’ll learn how to handle the response in the next chapter.

// Basic GET request
fetch('https://api.example.com/users') // URL of the API endpoint or resource
.then(response => {
// First step: check if the request was successful (status code 200-299)
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// Second step: parse the response body (e.g., as JSON)
return response.json(); // returns another promise
})
.then(data => {
// Third step: use the parsed data
console.log('Data received:', data);
})
.catch(error => {
// Handle network errors or errors thrown in the .then() blocks
console.error('Fetch error:', error);
});
// Using async/await (often preferred for readability)
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Data received (async/await):', data);
} catch (error) {
console.error('Fetch error (async/await):', error);
}
}
fetchData('https://api.example.com/users');

Note: fetch() only rejects its promise on network failure (e.g., DNS error, no connection). HTTP error statuses like 404 (Not Found) or 500 (Server Error) do not cause the promise to reject. You must check response.ok or response.status manually.

fetch() can accept an optional second argument, an init object, to customize the request (method, headers, body, etc.).

OptionDescription
methodThe HTTP request method, e.g., ‘GET’ (default), ‘POST’, ‘PUT’, ‘DELETE’, ‘PATCH’, ‘HEAD’.
headersAn object or Headers object containing request headers, e.g., { 'Content-Type': 'application/json', 'Accept': 'application/json' }.
bodyThe request body. Can be a string, Blob, BufferSource, FormData, URLSearchParams, or ReadableStream. Must match the Content-Type header. Often used with POST, PUT, PATCH.
modeControls handling of cross-origin requests, e.g., ‘cors’ (default), ‘no-cors’, ‘same-origin’.
cacheControls how the request interacts with the browser’s HTTP cache, e.g., ‘default’, ‘no-store’, ‘reload’.
credentialsControls whether cookies are sent with the request, e.g., ‘include’, ‘same-origin’ (default), ‘omit’.

GET: Used to request data from a specified resource. Data is often sent via URL query parameters. Should not change server state (idempotent). Requests can be cached and bookmarked.

POST: Used to submit data to be processed to a specified resource (e.g., create a new item, submit a form). Data is sent in the request body. Can change server state. Requests are not typically cached or bookmarked.

For GET requests, data is usually appended to the URL.

// Manually constructing the URL
const userId = 123;
fetch(`/api/users/${userId}?include=profile&theme=dark`);
// Using URLSearchParams for safer encoding
const params = new URLSearchParams({
include: 'profile',
theme: 'dark'
});
fetch(`/api/users/${userId}?${params.toString()}`);

To send JSON data using POST:

  • Set method to 'POST'.
  • Set the Content-Type header to 'application/json'.
  • Provide the JSON data (as a string) in the body option using JSON.stringify().
async function createUser(userData) {
try {
const response = await fetch('/api/users', {
method: 'POST', // Specify the method
headers: {
'Content-Type': 'application/json' // Indicate we're sending JSON
},
body: JSON.stringify(userData) // Convert the JS object to a JSON string
});
if (!response.ok) {
// Handle potential errors (e.g., validation errors from the server)
const errorData = await response.json().catch(() => ({ message: 'Unknown error' })); // Try to parse error details
throw new Error(`Failed to create user: ${response.status} - ${errorData.message}`);
}
const createdUser = await response.json(); // Get the newly created user data
console.log('User created:', createdUser);
return createdUser;
} catch (error) {
console.error('Error creating user:', error);
}
}
const newUser = { name: 'Jane Doe', email: 'jane.doe@example.com' };
createUser(newUser);

For security reasons, browsers restrict web pages from making requests to a different domain (origin) than the one that served the page. If your frontend code (e.g., at mysite.com) tries to fetch data from an API at a different domain (e.g., api.externalservice.com), the browser will block the request unless the server at api.externalservice.com includes specific CORS headers (like Access-Control-Allow-Origin) in its response.

If you encounter CORS errors in the browser console, it usually means the server needs to be configured to allow requests from your frontend’s origin. This is not something you typically fix purely on the client-side (unless using modes like ‘no-cors’ which has limitations).

Learn more about fetch() on MDN: https://developer.mozilla.org/en-US/docs/Web/API/fetch