Skillversitas

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().