Docs

README

11.3 Fetch API and HTTP

Overview

The Fetch API provides a modern, Promise-based way to make HTTP requests in JavaScript. It's the successor to XMLHttpRequest (XHR) and offers a cleaner, more powerful interface.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Fetch API Flow                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   JavaScript             Network               Server            β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”Œβ”€β”€β”€β”€β”€β”€β”€β”           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚   β”‚         │──fetch()──▢│       │──Request──▢│         β”‚         β”‚
β”‚   β”‚  Code   β”‚           β”‚  HTTP β”‚           β”‚   API   β”‚         β”‚
β”‚   β”‚         │◀─Promise──│       │◀─Response─│         β”‚         β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β””β”€β”€β”€β”€β”€β”€β”€β”˜           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β”‚                                                                  β”‚
β”‚   fetch(url, options)                                            β”‚
β”‚        β”‚                                                         β”‚
β”‚        β–Ό                                                         β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                           β”‚
β”‚   β”‚    Promise      β”‚                                           β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚                                           β”‚
β”‚   β”‚  β”‚ Response  β”‚  β”‚ β†’ Headers, Status, Body                   β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚                                           β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                           β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

HTTP Methods

MethodPurposeHas BodyIdempotent
GETRetrieve dataNoYes
POSTCreate resourceYesNo
PUTReplace resourceYesYes
PATCHPartial updateYesNo
DELETERemove resourceOptionalYes
HEADGet headers onlyNoYes
OPTIONSCheck capabilitiesNoYes

Basic Fetch Syntax

// GET request (default)
fetch('https://api.example.com/data')
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error(error));

// With async/await
async function getData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Fetch failed:', error);
  }
}

Fetch Options

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Fetch Request Options                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   fetch(url, {                                                   β”‚
β”‚       method: 'POST',           // HTTP method                   β”‚
β”‚       headers: {                // Request headers               β”‚
β”‚           'Content-Type': 'application/json',                    β”‚
β”‚           'Authorization': 'Bearer token123'                     β”‚
β”‚       },                                                         β”‚
β”‚       body: JSON.stringify(data), // Request body                β”‚
β”‚       mode: 'cors',             // cors, no-cors, same-origin    β”‚
β”‚       credentials: 'include',   // include, same-origin, omit    β”‚
β”‚       cache: 'no-cache',        // Cache mode                    β”‚
β”‚       redirect: 'follow',       // follow, error, manual         β”‚
β”‚       signal: controller.signal // AbortController signal        β”‚
β”‚   })                                                             β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Response Object

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Response Object                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   response.ok          β”‚ Boolean: true if status 200-299        β”‚
β”‚   response.status      β”‚ HTTP status code (200, 404, etc.)      β”‚
β”‚   response.statusText  β”‚ Status message ("OK", "Not Found")     β”‚
β”‚   response.headers     β”‚ Headers object                         β”‚
β”‚   response.url         β”‚ Final URL after redirects              β”‚
β”‚   response.type        β”‚ basic, cors, error, opaque             β”‚
β”‚   response.redirected  β”‚ Whether response is redirected         β”‚
β”‚                        β”‚                                         β”‚
β”‚   Body Methods (return Promises):                                β”‚
β”‚   ──────────────────────────────                                β”‚
β”‚   response.json()      β”‚ Parse as JSON                          β”‚
β”‚   response.text()      β”‚ Parse as text string                   β”‚
β”‚   response.blob()      β”‚ Parse as binary Blob                   β”‚
β”‚   response.arrayBuffer()β”‚ Parse as ArrayBuffer                  β”‚
β”‚   response.formData()  β”‚ Parse as FormData                      β”‚
β”‚                                                                  β”‚
β”‚   ⚠️ Body can only be read ONCE!                                β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Common Content Types

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Content-Type Headers                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                 β”‚
β”‚   application/json           β”‚ JSON data                       β”‚
β”‚   application/x-www-form-urlencoded β”‚ Form data (default)      β”‚
β”‚   multipart/form-data        β”‚ File uploads                    β”‚
β”‚   text/plain                 β”‚ Plain text                      β”‚
β”‚   text/html                  β”‚ HTML content                    β”‚
β”‚   application/octet-stream   β”‚ Binary data                     β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Error Handling

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Fetch Error Handling                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   ⚠️ IMPORTANT: Fetch only rejects on network errors!           β”‚
β”‚                                                                  β”‚
β”‚   HTTP 404 or 500 β†’ Promise RESOLVES (response.ok = false)      β”‚
β”‚   Network failure β†’ Promise REJECTS                              β”‚
β”‚                                                                  β”‚
β”‚   Correct Error Handling:                                        β”‚
β”‚   ──────────────────────                                        β”‚
β”‚   async function fetchWithErrorHandling(url) {                  β”‚
β”‚       const response = await fetch(url);                        β”‚
β”‚                                                                  β”‚
β”‚       if (!response.ok) {                                       β”‚
β”‚           throw new Error(`HTTP ${response.status}`);           β”‚
β”‚       }                                                          β”‚
β”‚                                                                  β”‚
β”‚       return response.json();                                   β”‚
β”‚   }                                                              β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Request/Response Headers

// Creating headers
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer token');

// Or as object
const headers2 = new Headers({
  'Content-Type': 'application/json',
});

// Headers methods
headers.get('Content-Type'); // Get value
headers.has('Authorization'); // Check existence
headers.set('X-Custom', 'value'); // Set value
headers.delete('X-Custom'); // Delete header
headers.entries(); // Iterator

AbortController - Canceling Requests

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Request Cancellation                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   const controller = new AbortController();                      β”‚
β”‚   const { signal } = controller;                                 β”‚
β”‚                                                                  β”‚
β”‚   fetch(url, { signal })                                         β”‚
β”‚       .then(response => response.json())                         β”‚
β”‚       .catch(err => {                                            β”‚
β”‚           if (err.name === 'AbortError') {                       β”‚
β”‚               console.log('Request cancelled');                  β”‚
β”‚           }                                                      β”‚
β”‚       });                                                        β”‚
β”‚                                                                  β”‚
β”‚   // Later, to cancel:                                           β”‚
β”‚   controller.abort();                                            β”‚
β”‚                                                                  β”‚
β”‚   // With timeout:                                               β”‚
β”‚   const timeoutId = setTimeout(() => controller.abort(), 5000);  β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Common Request Patterns

GET with Query Parameters

const params = new URLSearchParams({
  page: 1,
  limit: 10,
  search: 'javascript',
});

fetch(`https://api.example.com/items?${params}`).then((response) =>
  response.json()
);

POST with JSON

fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'John',
    email: 'john@example.com',
  }),
});

File Upload

const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('description', 'My file');

fetch('https://api.example.com/upload', {
  method: 'POST',
  body: formData,
  // Don't set Content-Type - browser sets it with boundary
});

CORS (Cross-Origin Resource Sharing)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     CORS Overview                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   Same-Origin: scheme + host + port must match                   β”‚
β”‚   ────────────────────────────────────────────                  β”‚
β”‚   http://example.com/page1                                       β”‚
β”‚   http://example.com/page2    ← Same origin βœ“                   β”‚
β”‚   https://example.com/page1   ← Different scheme βœ—              β”‚
β”‚   http://api.example.com      ← Different host βœ—                β”‚
β”‚   http://example.com:8080     ← Different port βœ—                β”‚
β”‚                                                                  β”‚
β”‚   CORS Headers (Server Response):                                β”‚
β”‚   ──────────────────────────────                                β”‚
β”‚   Access-Control-Allow-Origin: *                                 β”‚
β”‚   Access-Control-Allow-Methods: GET, POST, PUT                   β”‚
β”‚   Access-Control-Allow-Headers: Content-Type, Authorization      β”‚
β”‚   Access-Control-Allow-Credentials: true                         β”‚
β”‚                                                                  β”‚
β”‚   Preflight Request (OPTIONS):                                   β”‚
β”‚   ────────────────────────────                                  β”‚
β”‚   Sent automatically for:                                        β”‚
β”‚   β€’ Non-simple methods (PUT, DELETE, PATCH)                      β”‚
β”‚   β€’ Custom headers                                               β”‚
β”‚   β€’ Content-Type other than form-urlencoded, multipart, text     β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Credentials and Cookies

// Include cookies in same-origin requests
fetch(url, { credentials: 'same-origin' });

// Include cookies in cross-origin requests
fetch(url, { credentials: 'include' });

// Never include cookies
fetch(url, { credentials: 'omit' });

Retry Logic

async function fetchWithRetry(url, options = {}, retries = 3, delay = 1000) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, options);
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      return response;
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise((r) => setTimeout(r, delay * Math.pow(2, i)));
    }
  }
}

Streaming Responses

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Response Streaming                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   async function* streamResponse(response) {                     β”‚
β”‚       const reader = response.body.getReader();                  β”‚
β”‚       const decoder = new TextDecoder();                         β”‚
β”‚                                                                  β”‚
β”‚       while (true) {                                             β”‚
β”‚           const { done, value } = await reader.read();           β”‚
β”‚           if (done) break;                                       β”‚
β”‚           yield decoder.decode(value, { stream: true });         β”‚
β”‚       }                                                          β”‚
β”‚   }                                                              β”‚
β”‚                                                                  β”‚
β”‚   // Usage                                                       β”‚
β”‚   const response = await fetch(url);                             β”‚
β”‚   for await (const chunk of streamResponse(response)) {          β”‚
β”‚       console.log('Received:', chunk);                           β”‚
β”‚   }                                                              β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Best Practices

  1. β€’Always check response.ok - HTTP errors don't reject the Promise
  2. β€’Use AbortController for timeout and cancellation
  3. β€’Handle errors properly - network failures and HTTP errors
  4. β€’Set appropriate Content-Type - especially for POST/PUT
  5. β€’Use async/await for cleaner code
  6. β€’Consider retry logic for unreliable networks
  7. β€’Don't forget CORS when dealing with external APIs

Common Gotchas

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Common Mistakes                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   ❌ fetch(url).then(data => ...)                               β”‚
β”‚   βœ“  fetch(url).then(res => res.json()).then(data => ...)       β”‚
β”‚      (Response is not the data itself!)                          β”‚
β”‚                                                                  β”‚
β”‚   ❌ Assuming 404 will throw an error                           β”‚
β”‚   βœ“  Check response.ok before processing                         β”‚
β”‚                                                                  β”‚
β”‚   ❌ Reading body twice                                          β”‚
β”‚   βœ“  Clone response if you need to read it multiple times        β”‚
β”‚      const clone = response.clone();                             β”‚
β”‚                                                                  β”‚
β”‚   ❌ Setting Content-Type for FormData                           β”‚
β”‚   βœ“  Let browser set it (includes boundary for multipart)        β”‚
β”‚                                                                  β”‚
β”‚   ❌ Forgetting await with async functions                       β”‚
β”‚   βœ“  Always await fetch and body methods                         β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Browser Support

The Fetch API is supported in all modern browsers. For older browsers, use a polyfill like whatwg-fetch or node-fetch for Node.js environments.

Key Takeaways

  1. β€’Fetch is Promise-based and supports async/await
  2. β€’Check response.ok for HTTP errors
  3. β€’Body methods return Promises and can only be called once
  4. β€’Use AbortController for request cancellation
  5. β€’CORS restrictions apply to cross-origin requests
  6. β€’Proper error handling requires checking both network and HTTP errors
README - JavaScript Tutorial | DeepML