Making Requests
The Fetch API provides a modern way to make HTTP requests. It returns a Promise that resolves to a Response object.
Basic GET Request
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
With async/await
async function getUsers() {
try {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
return data;
} catch (error) {
console.error('Failed to fetch users:', error);
}
}
POST Request
async function createUser(userData) {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
// Usage
const newUser = await createUser({
name: 'John',
email: 'john@example.com'
});
Other HTTP Methods
// PUT
await fetch(url, { method: 'PUT', body: data });
// PATCH
await fetch(url, { method: 'PATCH', body: data });
// DELETE
await fetch(url, { method: 'DELETE' });
// HEAD
await fetch(url, { method: 'HEAD' });
Handling Responses
The Response object has methods to read the response body in different formats.
Response Properties
const response = await fetch('/api/data');
console.log(response.ok); // true if status 200-299
console.log(response.status); // 200
console.log(response.statusText); // 'OK'
console.log(response.headers); // Headers object
console.log(response.url); // Final URL after redirects
console.log(response.type); // 'basic', 'cors', etc.
Response Methods
// JSON
const data = await response.json();
// Text
const text = await response.text();
// Blob (for files, images)
const blob = await response.blob();
// ArrayBuffer (for binary data)
const buffer = await response.arrayBuffer();
// FormData
const formData = await response.formData();
Checking Response Status
async function fetchData() {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
Handling Different Status Codes
async function fetchWithStatusHandling() {
const response = await fetch('/api/data');
switch (response.status) {
case 200:
return response.json();
case 304:
return null; // Not modified
case 401:
throw new Error('Unauthorized');
case 404:
throw new Error('Not found');
case 500:
throw new Error('Server error');
default:
throw new Error(`Unexpected status: ${response.status}`);
}
}
Advanced Fetch Patterns
Real-world fetch usage often requires patterns for timeouts, abort controllers, and retry logic.
Request Timeout
function fetchWithTimeout(url, options = {}, timeout = 5000) {
return Promise.race([
fetch(url, options),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Request timeout')), timeout)
)
]);
}
// Usage
try {
const data = await fetchWithTimeout('/api/slow', {}, 3000);
} catch (error) {
console.error(error.message); // 'Request timeout'
}
Abort Controller
const controller = new AbortController();
const signal = controller.signal;
// Start request
fetch('/api/data', { signal })
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Request cancelled');
} else {
console.error('Fetch error:', error);
}
});
// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);
Retry Logic
async function fetchWithRetry(url, options = {}, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) return response;
} catch (error) {
if (i === retries - 1) throw error;
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
}
}
throw new Error('Max retries reached');
}
Interceptors Pattern
async function fetchWithInterceptors(url, options = {}) {
// Pre-request interceptor
const modifiedOptions = { ...options };
modifiedOptions.headers = {
...modifiedOptions.headers,
'Authorization': `Bearer ${getToken()}`
};
const response = await fetch(url, modifiedOptions);
// Post-response interceptor
if (response.status === 401) {
await refreshToken();
return fetch(url, modifiedOptions); // Retry
}
return response;
}
Practice Problems
Create a reusable React component implementing Fetch API. Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for Fetch API using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Fetch API for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. What does fetch() return?
2. How do you check if a fetch response was successful?
3. How do you cancel a fetch request?
4. What happens if fetch() encounters a network error?
Flashcards
Question
What is the Fetch API?
Click to reveal answer
Answer
A modern API for making HTTP requests that returns a Promise resolving to a Response object.
Question
How to read JSON from a fetch response?
Click to reveal answer
Answer
await response.json() - it also returns a Promise.
Question
What is response.ok?
Click to reveal answer
Answer
A boolean that's true if the HTTP status is 200-299 (success range).
Question
How to cancel a fetch request?
Click to reveal answer
Answer
Use AbortController: const controller = new AbortController(); fetch(url, { signal: controller.signal }); controller.abort();
Question
What is Fetch API?
Click to reveal answer
Answer
Fetch API is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.fetch() returns a Promise that resolves to a Response object
- 2.Always check response.ok or response.status before reading the body
- 3.Use AbortController to cancel requests
- 4.Network errors reject the Promise, they don't return error status codes
- 5.Use async/await with fetch for cleaner code
Interview Tips
- •Explain the difference between fetch errors and HTTP error status codes
- •Demonstrate how to implement a request timeout
- •Discuss when to use AbortController
- •Compare fetch with XMLHttpRequest or axios
Cheat Sheet
Fetch API Cheat Sheet
Basic Request
const response = await fetch(url);
const data = await response.json();
POST Request
await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
Response Properties
response.ok- true if 200-299response.status- HTTP status coderesponse.headers- Response headers
Response Methods
.json()- Parse as JSON.text()- Parse as text.blob()- Parse as Blob
Advanced
- AbortController for cancellation
- Promise.race() for timeouts