Skip to main content
โšก Calmops

Fetch API: Making HTTP Requests

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

Official Documentation

Next Steps

  1. Error Handling with Promises and Async/Await
  2. XMLHttpRequest and AJAX
  3. Async/Await: Modern Asynchronous Programming

Comments