Fetch API
The Fetch API is the modern way to make HTTP requests in JavaScript. It replaces XMLHttpRequest with cleaner, Promise-based syntax. It can be used for GET, POST, PUT, DELETE — all the HTTP methods you need.
Code Example
GET — Fetch Data
// Basic fetch — returns a Promise
fetch('https://api.university.edu/student')
.then(response => {
console.log(response.status); // 200
console.log(response.ok); // true
return response.json(); // parse JSON
})
.then(data => {
console.log(data); // array of student objects
})
.catch(error => {
console.error('Failed to fetch data:', error);
});
POST — Add Data
fetch('https://api.university.edu/student', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
studentId: '2024001',
name: 'Mike Johnson',
major: 'Computer Science',
year: '2024'
})
})
.then(response => response.json())
.then(data => {
console.log('Berresult add:', data);
})
.catch(error => {
console.error('Error:', error);
});
PUT — Update Data
fetch('https://api.university.edu/student/2024001', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Mike Johnson (updated)',
major: 'Information Systems'
})
})
.then(response => {
if (!response.ok) throw new Error('Update failed');
return response.json();
})
.then(data => console.log('Updated:', data));
DELETE — Remove Data
fetch('https://api.university.edu/student/2024001', {
method: 'DELETE'
})
.then(response => {
if (!response.ok) throw new Error('Delete failed');
return response.json();
})
.then(data => console.log('Deleted:', data));
Code Explanation
The Response Object
fetch('/api/data')
.then(response => {
console.log(response.status); // 200, 404, 500, etc.
console.log(response.ok); // true if 200-299
console.log(response.statusText); // "OK", "Not Found", etc.
console.log(response.url); // final URL (after redirect)
console.log(response.headers); // Headers object
// Read headers
const contentType = response.headers.get('Content-Type');
const auth = response.headers.get('Authorization');
});
Reading the Response
// JSON
const data = await response.json();
// Plain text
const text = await response.text();
// Blob (for files, images)
const blob = await response.blob();
// ArrayBuffer (for binary data)
const buffer = await response.arrayBuffer();
// Form data
const formData = await response.formData();
Headers
// Set headers
fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123',
'X-Custom-Header': 'custom-value'
},
body: JSON.stringify(payload)
});
// Headers from an object
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer token123');
fetch('/api/data', { headers });
Proper Error Handling
// fetch does NOT reject on HTTP errors (404, 500)
// It only rejects on network errors
// So you must check response.ok
fetch('/api/student')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => {
// Catches network errors AND HTTP errors that were thrown
console.error('Request failed:', error.message);
});
Query Parameters
// Manual way
const params = new URLSearchParams({
major: 'Computer Science',
year: '2024',
page: '1'
});
fetch(`/api/student?${params.toString()}`)
.then(res => res.json())
.then(data => console.log(data));
// URL: /api/student?major=Computer+Science&year=2024&page=1
Real-World Examples
CRUD Student Data with a Backend API
const API_URL = 'https://api.university.edu/student';
// ============ GET — Fetch all students ============
async function fetchAllStudents() {
try {
const response = await fetch(API_URL);
if (!response.ok) throw new Error('Failed to fetch data');
const data = await response.json();
renderTable(data);
} catch (error) {
showError('Unable to load student data: ' + error.message);
}
}
// ============ GET — Fetch one student ============
async function fetchStudent(studentId) {
const response = await fetch(`${API_URL}/${studentId}`);
if (!response.ok) throw new Error(`Student ${studentId} not found`);
return response.json();
}
// ============ POST — Add a new student ============
async function addStudent(data) {
try {
const response = await fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (!response.ok) {
const err = await response.json();
throw new Error(err.message || 'Failed to add student');
}
const result = await response.json();
showNotification('Berresult menambahkan ' + result.name, 'success');
return result;
} catch (error) {
showNotification(error.message, 'error');
throw error;
}
}
// ============ PUT — Update a student ============
async function updateStudent(studentId, data) {
const response = await fetch(`${API_URL}/${studentId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (!response.ok) throw new Error('Failed to update');
return response.json();
}
// ============ DELETE — Remove a student ============
async function removeStudent(studentId) {
const confirmed = confirm(`Delete student ${studentId}?`);
if (!confirmed) return;
const response = await fetch(`${API_URL}/${studentId}`, {
method: 'DELETE'
});
if (!response.ok) throw new Error('Failed to delete');
showNotification(`Student ${studentId} removed successfully`, 'success');
fetchAllStudents(); // refresh the table
}
// ============ Integration with a Form ============
document.querySelector('#form-student').addEventListener('submit', async function (e) {
e.preventDefault();
const formData = new FormData(this);
const data = Object.fromEntries(formData);
try {
await addStudent(data);
this.reset();
} catch (error) {
console.error(error);
}
});
File Upload
async function uploadFile(file) {
const formData = new FormData();
formData.append('file', file);
formData.append('studentId', '2024001');
const response = await fetch('/api/upload', {
method: 'POST',
body: formData // DO NOT set Content-Type manually; the browser handles it
});
return response.json();
}
// Usage
document.querySelector('#input-file').addEventListener('change', function () {
const file = this.files[0];
if (file) {
uploadFile(file).then(result => {
console.log('File uploaded:', result.url);
});
}
});
Fetch with a Timeout
async function fetchWithTimeout(url, options = {}, timeout = 5000) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
...options,
signal: controller.signal
});
clearTimeout(id);
return response;
} catch (error) {
clearTimeout(id);
if (error.name === 'AbortError') {
throw new Error('Request timeout');
}
throw error;
}
}
Fetch with an Auth Token
async function fetchAuth(url, options = {}) {
const token = localStorage.getItem('authToken');
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
...options.headers
}
});
if (response.status === 401) {
localStorage.removeItem('authToken');
window.location.href = '/login';
return;
}
return response;
}
Important Status Codes
200 OK — the request succeeded
201 Created — a new resource was created successfully
204 No Content — deletion succeeded, no response body
400 Bad Request — the sent data is invalid
401 Unauthorized — no authentication
403 Forbidden — no access permission
404 Not Found — the resource was not found
500 Server Error — an error on the server
Conclusion
The Fetch API is the modern standard for HTTP requests. Always check response.ok because fetch doesn't automatically reject on HTTP errors. Use async/await for cleaner code. For file uploads, use FormData and don't set Content-Type manually. Always handle errors with try/catch or .catch().