Fetch API: Making HTTP Requests
The Fetch API provides a modern way to make HTTP requests in JavaScript, replacing the older XMLHttpRequest.
Basic Fetch
GET Request
fetch("https://api.example.com/users")
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
Async/Await
async function getUsers() {
try {
const response = await fetch("https://api.example.com/users");
const data = await response.json();
console.log(data);
} catch (error) {
console.error(error);
}
}
getUsers();
Response Object
The fetch returns a Response object:
fetch("https://api.example.com/users")
.then(response => {
console.log(response.status); // 200
console.log(response.statusText); // "OK"
console.log(response.headers); // Headers object
console.log(response.ok); // true if status 200-299
return response.json();
})
.then(data => console.log(data));
Response Methods
json()
Parse response as JSON:
const response = await fetch("https://api.example.com/users");
const data = await response.json();
console.log(data);
text()
Get response as text:
const response = await fetch("https://api.example.com/data.txt");
const text = await response.text();
console.log(text);
blob()
Get response as binary data:
const response = await fetch("https://api.example.com/image.png");
const blob = await response.blob();
const url = URL.createObjectURL(blob);
arrayBuffer()
Get response as ArrayBuffer:
const response = await fetch("https://api.example.com/data.bin");
const buffer = await response.arrayBuffer();
Request Options
POST Request
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "Alice",
email: "[email protected]"
})
});
const data = await response.json();
console.log(data);
PUT Request
const response = await fetch("https://api.example.com/users/1", {
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "Alice Updated",
email: "[email protected]"
})
});
const data = await response.json();
console.log(data);
DELETE Request
const response = await fetch("https://api.example.com/users/1", {
method: "DELETE"
});
console.log(response.ok); // true if successful
PATCH Request
const response = await fetch("https://api.example.com/users/1", {
method: "PATCH",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
email: "[email protected]"
})
});
const data = await response.json();
console.log(data);
Headers
Setting Headers
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer token123",
"X-Custom-Header": "value"
},
body: JSON.stringify({ name: "Alice" })
});
Reading Headers
const response = await fetch("https://api.example.com/users");
console.log(response.headers.get("content-type")); // "application/json"
console.log(response.headers.get("content-length")); // "1234"
Error Handling
Check Response Status
async function fetchUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
try {
const user = await fetchUser(1);
console.log(user);
} catch (error) {
console.error(error);
}
Network Errors
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
return await response.json();
} catch (error) {
// Network error or parsing error
console.error("Fetch failed:", error);
}
}
Practical Examples
Fetch with Retry
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
if (i === maxRetries - 1) throw error;
console.log(`Retry ${i + 1}...`);
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
}
fetchWithRetry("https://api.example.com/data")
.then(data => console.log(data))
.catch(error => console.error(error));
Fetch with Timeout
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timeoutId);
return await response.json();
} catch (error) {
clearTimeout(timeoutId);
if (error.name === "AbortError") {
throw new Error("Request timeout");
}
throw error;
}
}
fetchWithTimeout("https://api.example.com/data", 5000)
.then(data => console.log(data))
.catch(error => console.error(error));
Parallel Requests
async function fetchMultiple() {
try {
const [users, posts, comments] = await Promise.all([
fetch("https://api.example.com/users").then(r => r.json()),
fetch("https://api.example.com/posts").then(r => r.json()),
fetch("https://api.example.com/comments").then(r => r.json())
]);
return { users, posts, comments };
} catch (error) {
console.error(error);
}
}
fetchMultiple().then(data => console.log(data));
Upload File
async function uploadFile(file) {
const formData = new FormData();
formData.append("file", file);
const response = await fetch("https://api.example.com/upload", {
method: "POST",
body: formData
});
return await response.json();
}
const fileInput = document.getElementById("fileInput");
fileInput.addEventListener("change", async (event) => {
const file = event.target.files[0];
const result = await uploadFile(file);
console.log(result);
});
Search with Debounce
function debounce(fn, delay) {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
};
}
const searchInput = document.getElementById("search");
const search = debounce(async (query) => {
const response = await fetch(`https://api.example.com/search?q=${query}`);
const results = await response.json();
console.log(results);
}, 300);
searchInput.addEventListener("input", (event) => {
search(event.target.value);
});
Pagination
async function fetchPage(page = 1, pageSize = 10) {
const response = await fetch(
`https://api.example.com/users?page=${page}&pageSize=${pageSize}`
);
return await response.json();
}
async function loadMore() {
let page = 1;
while (true) {
const data = await fetchPage(page);
if (data.items.length === 0) break;
console.log(data.items);
page++;
}
}
AbortController
Cancel requests:
const controller = new AbortController();
const response = await fetch("https://api.example.com/data", {
signal: controller.signal
});
// Cancel the request
controller.abort();
Timeout with AbortController
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timeoutId);
return await response.json();
} catch (error) {
clearTimeout(timeoutId);
throw error;
}
}
CORS
Cross-Origin Resource Sharing:
// Include credentials
const response = await fetch("https://api.example.com/data", {
method: "GET",
credentials: "include", // Include cookies
headers: {
"Content-Type": "application/json"
}
});
// Or use 'same-origin' or 'omit'
Summary
- fetch(): make HTTP requests
- Response: object with status, headers, body
- json(): parse response as JSON
- text(): get response as text
- method: GET, POST, PUT, DELETE, PATCH
- headers: set request headers
- body: request body (JSON, FormData, etc.)
- AbortController: cancel requests
- Error handling: check response.ok
- Best practice: use async/await with try-catch
Related Resources
Official Documentation
Next Steps
- Error Handling with Promises and Async/Await
- XMLHttpRequest and AJAX
- Async/Await: Modern Asynchronous Programming
Comments