Modern Networking with Fetch

Chapter 4: Modern Networking with Fetch

The Fetch API is the modern standard for performing asynchronous network requests. This chapter provides a comprehensive technical reference for the fetch() function, the Request and Response interfaces, and advanced streaming patterns.


I. The fetch() API Reference

The fetch() method starts the process of fetching a resource from the network, returning a promise which resolves to the Response object representing the response to that request.

1. Function Syntax

const promise = fetch(resource [, options]);

2. Parameters

ParameterTypeDescription
resourcestring | Request | URLThe URL of the resource or a Request object.
optionsObject (Optional)An object containing custom settings for the request (see below).

3. The options (RequestInit) Object

The options object allows for granular control over the HTTP request.

PropertyTypeDefaultDescription
methodstring'GET'HTTP request method ('POST', 'PUT', 'DELETE', etc.).
headersHeaders | Object{}Any headers to add to the request.
bodystring | Blob | FormData | URLSearchParamsnullThe body of the request (not allowed for GET or HEAD).
modestring'cors'The mode of the request ('cors', 'no-cors', 'same-origin').
credentialsstring'same-origin'Controls cookies ('omit', 'same-origin', 'include').
cachestring'default'Cache mode ('default', 'no-store', 'reload', 'no-cache', 'force-cache').
redirectstring'follow'How to handle redirects ('follow', 'error', 'manual').
referrerstring'about:client'Referrer information for the request.
integritystring""Subresource Integrity (SRI) value for security verification.
keepalivebooleanfalseAllows the request to outlive the page.
signalAbortSignalnullAn instance of AbortSignal to cancel the request.

II. The Response Object

When the fetch() promise resolves, it returns a Response instance.

1. Instance Properties (Read-only)

PropertyTypeDescription
okbooleantrue if status is in the range 200–299.
statusnumberThe HTTP status code (e.g., 200, 404).
statusTextstringThe status message (e.g., "OK", "Not Found").
headersHeadersThe Headers object associated with the response.
urlstringThe final URL of the response after any redirects.
typestringThe type of the response ('basic', 'cors', 'error').
bodyUsedbooleantrue if the body has already been read.

2. Body Consumption Methods

Every method returns a Promise that resolves with the parsed data. Note: The body can only be consumed once.

MethodReturn Type (Resolved)Description
.json()anyParses the body as a JSON object.
.text()stringReturns the body as a plain text string.
.blob()BlobReturns the body as a binary Blob object.
.arrayBuffer()ArrayBufferReturns the body as a raw binary ArrayBuffer.
.formData()FormDataParses the body as a FormData object.

III. Error Handling & The AbortController

1. Network Errors vs. HTTP Errors

A critical distinction in fetch() is that HTTP error status codes (404, 500) do not cause the promise to reject.

  • Promise Rejects: Only on network failure, DNS issues, or CORS violations.
  • Promise Resolves: On any valid HTTP response (even 404).
// Production Standard Implementation
async function safeFetch(url) {
  try {
    const response = await fetch(url);
    
    // Check for HTTP errors
    if (!response.ok) {
      throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
    }
    
    return await response.json();
  } catch (error) {
    // Catch network errors AND our manually thrown HTTP errors
    console.error('Fetch failed:', error.message);
  }
}

2. Request Cancellation (AbortController)

Use AbortController to implement timeouts or cancel requests when components unmount.

const controller = new AbortController();
const signal = controller.signal;

// Trigger cancellation after 3 seconds
const timeoutId = setTimeout(() => controller.abort(), 3000);

try {
  const response = await fetch('/api/large-resource', { signal });
  const data = await response.json();
} catch (err) {
  if (err.name === 'AbortError') {
    console.warn('Request was aborted');
  } else {
    console.error('Another error occurred:', err);
  }
} finally {
  clearTimeout(timeoutId);
}

IV. Advanced Patterns

1. HTTP/2 and Performance

Unlike HTTP/1.1, fetch() over HTTP/2 uses multiplexing. This allows multiple requests to be sent over a single TCP connection without "head-of-line blocking."

BrowserServerSingle Multiplexed TCP Connection (HTTP/2)

2. Response Cloning

If you need to read the body multiple times, use .clone().

const response = await fetch('/api/data');
const logClone = response.clone();

const data = await response.json(); // Consumes body
const raw = await logClone.text();   // Also works because of cloning

V. Core Engineering Standards

1. Security Mandates

  • CORS Handling: Always wrap cross-origin requests in a try/catch block, as CORS failures result in a TypeError.
  • Sensitive Data: Never include API keys in the URL query string. Always prefer Authorization: Bearer <token> in the headers object.
  • CSRF Protection: For state-changing requests (POST, PUT, DELETE), ensure the X-Requested-With: XMLHttpRequest or a CSRF token header is present.

2. Performance Mandates

  • Body Parsing: Never parse the body if the response is not ok. This saves memory and prevents unexpected errors.
  • Keep-alive: Use keepalive: true for "fire and forget" tracking requests to ensure they finish even if the user closes the tab.

Network Latency: [12ms ]