JavaScript Fetch API

Basic GET

Fetch and parse JSON
const response = await fetch("https://api.example.com/hosts");
if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const hosts = await response.json();
console.log(hosts);

fetch returns a Response object. .ok is true for status 200-299. The body is a stream — call .json(), .text(), or .blob() to consume it.

POST with JSON

Send data to an API
const newHost = { name: "sw02", ip: "10.50.1.11", port: 22 };

const response = await fetch("https://api.example.com/hosts", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`,
    },
    body: JSON.stringify(newHost),
});

if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message);
}

const created = await response.json();
console.log("Created:", created.id);

The body must be a string, Blob, FormData, or ReadableStream. JSON.stringify converts objects to JSON strings.

Request Options

Full set of fetch options
const response = await fetch(url, {
    method: "PUT",                       // GET, POST, PUT, PATCH, DELETE
    headers: {
        "Content-Type": "application/json",
        "Accept": "application/json",
    },
    body: JSON.stringify(data),
    signal: AbortSignal.timeout(5000),   // timeout (modern)
    credentials: "include",              // send cookies cross-origin
    cache: "no-cache",                   // cache control
});

Abort and Timeout

Cancel in-flight requests
// AbortController — manual cancellation
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);  // cancel after 5s

try {
    const res = await fetch(url, { signal: controller.signal });
    const data = await res.json();
} catch (err) {
    if (err.name === "AbortError") {
        console.log("Request was cancelled");
    }
}

// Built-in timeout (modern browsers, Node 18+)
const res = await fetch(url, {
    signal: AbortSignal.timeout(5000),
});

AbortController lets you cancel fetch requests, event listeners, and any async operation that accepts an AbortSignal.

Error Handling

fetch only rejects on network failure
// Wrapper that throws on HTTP errors
async function api(url, options = {}) {
    const response = await fetch(url, {
        headers: { "Content-Type": "application/json" },
        ...options,
    });

    if (!response.ok) {
        const body = await response.text();
        throw new Error(`${response.status} ${response.statusText}: ${body}`);
    }

    return response.json();
}

// Usage
try {
    const hosts = await api("/api/hosts");
} catch (err) {
    console.error("API error:", err.message);
}

fetch does not throw on 404 or 500 — it resolves with a Response where .ok is false. Always check .ok or the status code.

Streaming

Process large responses incrementally
const response = await fetch("/api/large-dataset");
const reader = response.body.getReader();
const decoder = new TextDecoder();

let result = "";
while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    result += decoder.decode(value, { stream: true });
}
console.log(result);

Streaming is useful for large responses, server-sent events, and progress tracking.