Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungYour AI Agent Is a Confused Deputy(19.09.2026 um 21:39 Uhr)
Sichere ProgrammierungJour 1/100 · 75 minutes(19.09.2026 um 21:40 Uhr)
Sichere ProgrammierungMOGP: A SCSS Layout System That Only Does One Thing(19.09.2026 um 21:42 Uhr)
Sichere ProgrammierungAuto-localize prices in React with react-currency-localizer-realtime(19.09.2026 um 21:50 Uhr)
Sichere ProgrammierungYour AI Agent Is a Confused Deputy(19.09.2026 um 21:39 Uhr)
Sichere ProgrammierungJour 1/100 · 75 minutes(19.09.2026 um 21:40 Uhr)
Sichere ProgrammierungMOGP: A SCSS Layout System That Only Does One Thing(19.09.2026 um 21:42 Uhr)
Sichere ProgrammierungAuto-localize prices in React with react-currency-localizer-realtime(19.09.2026 um 21:50 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Mastering the Fetch API: Practical Patterns for Real-World Apps

Mastering the Fetch API: Practical Patterns for Real-World Apps

Fetch is more powerful than most developers realize.

The Basics (Quick Refresher)

// GET request
const response = await fetch('https://api.example.com/data');
const data = await response.json();

// POST request
const response = await fetch('https://api.example.com/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Alex', email: '[email protected]' }),
});

A Robust Fetch Wrapper

class ApiClient {
  constructor(baseURL, options = {}) {
    this.baseURL = baseURL;
    this.timeout = options.timeout || 10000;
    this.headers = {
      'Content-Type': 'application/json',
      ...options.headers,
    };
  }

  async request(endpoint, options = {}) {
    const url = `${this.baseURL}${endpoint}`;

    // Abort controller for timeout
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), this.timeout);

    try {
      const response = await fetch(url, {
        ...options,
        headers: { ...this.headers, ...options.headers },
        signal: controller.signal,
      });

      clearTimeout(timeoutId);

      if (!response.ok) {
        throw new ApiError(response.status, await this.parseError(response));
      }

      return response;
    } catch (error) {
      clearTimeout(timeoutId);

      if (error.name === 'AbortError') {
        throw new Error(`Request timed out after ${this.timeout}ms`);
      }

      throw error;
    }
  }

  async get(endpoint, params = {}) {
    const query = new URLSearchParams(params).toString();
    const url = query ? `${endpoint}?${query}` : endpoint;
    const response = await this.request(url);
    return response.json();
  }

  async post(endpoint, data) {
    const response = await this.request(endpoint, {
      method: 'POST',
      body: JSON.stringify(data),
    });
    return response.json();
  }

  async put(endpoint, data) {
    const response = await this.request(endpoint, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
    return response.json();
  }

  async delete(endpoint) {
    const response = await this.request(endpoint, { method: 'DELETE' });
    return response.status === 204 || response.json();
  }

  async parseError(response) {
    try {
      return await response.json();
    } catch {
      return { message: response.statusText };
    }
  }
}

class ApiError extends Error {
  constructor(statusCode, errorBody) {
    super(errorBody.message || `API Error ${statusCode}`);
    this.statusCode = statusCode;
    this.errorBody = errorBody;
  }
}

// Usage:
const api = new ApiClient('https://api.example.com', {
  timeout: 5000,
  headers: { Authorization: `Bearer ${token}` },
});

try {
  const users = await api.get('/users', { page: 1, limit: 20 });
  console.log(users);
} catch (error) {
  if (error instanceof ApiError) {
    console.error(`${error.statusCode}:`, error.errorBody);
  }
}

Request Caching

class CachedFetch {
  #cache = new Map();

  async get(url, ttlMs = 60000) {
    const cached = this.#cache.get(url);

    if (cached && Date.now() - cached.timestamp < ttlMs) {
      return cached.data; // Return cache hit
    }

    const data = await fetch(url).then(r => r.json());
    this.#cache.set(url, { data, timestamp: Date.now() });
    return data;
  }

  invalidate(url) {
    this.#cache.delete(url);
  }

  clear() {
    this.#cache.clear();
  }
}

const cachedApi = new CachedFetch();

// These two calls only make ONE HTTP request
const [data1, data2] = await Promise.all([
  cachedApi.get('/api/data'),
  cachedApi.get('/api/data'), // Cache hit!
]);

Retry Logic with Exponential Backoff

async function fetchWithRetry(url, options = {}) {
  const {
    maxRetries = 3,
    baseDelay = 1000,
    backoffFactor = 2,
    retryableStatuses = [408, 429, 500, 502, 503, 504],
  } = options;

  let lastError;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options.fetchOptions);

      if (response.ok || !retryableStatuses.includes(response.status)) {
        return response;
      }

      // Retryable server error — don't throw, retry instead
      lastError = new Error(`HTTP ${response.status}`);
    } catch (error) {
      lastError = error;
    }

    if (attempt < maxRetries) {
      const delay = baseDelay * Math.pow(backoffFactor, attempt);
      console.warn(`Attempt ${attempt + 1} failed. Retrying in ${delay}ms...`);
      await sleep(delay);
    }
  }

  throw lastError;
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Concurrent Requests

// Parallel: All requests run simultaneously
async function loadDashboardData(userId) {
  const [user, posts, notifications, friends] = await Promise.all([
    fetch(`/api/users/${userId}`).then(r => r.json()),
    fetch(`/api/users/${userId}/posts`).then(r => r.json()),
    fetch(`/api/notifications`).then(r => r.json()),
    fetch(`/api/users/${userId}/friends`).then(r => r.json()),
  ]);

  return { user, posts, notifications, friends };
}

// Race: Use fastest successful response
async function fetchWithFallback(primaryUrl, fallbackUrl) {
  try {
    const result = await Promise.any([
      fetch(primaryUrl).then(r => r.json()),
      fetch(fallbackUrl).then(r => r.json()),
    ]);
    return result;
  } catch {
    throw new Error('All endpoints failed');
  }
}

// Batched: Process in groups to avoid overwhelming the server
async function batchFetch(urls, batchSize = 5) {
  const results = [];
  for (let i = 0; i < urls.length; i += batchSize) {
    const batch = urls.slice(i, i + batchSize);
    const batchResults = await Promise.all(
      batch.map(url => fetch(url).then(r => r.json()).catch(() => null))
    );
    results.push(...batchResults);
  }
  return results.filter(Boolean);
}

Progress Tracking for Uploads

async function uploadWithProgress(file, url, onProgress) {
  const xhr = new XMLHttpRequest();

  return new Promise((resolve, reject) => {
    xhr.upload.addEventListener('progress', (e) => {
      if (e.lengthComputable) {
        const percent = Math.round((e.loaded / e.total) * 100);
        onProgress(percent, e.loaded, e.total);
      }
    });

    xhr.addEventListener('load', () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve(JSON.parse(xhr.responseText));
      } else {
        reject(new Error(`Upload failed: ${xhr.status}`));
      }
    });

    xhr.addEventListener('error', () => reject(new Error('Network error')));
    xhr.open('POST', url);
    xhr.send(file);
  });
}

// Usage:
uploadWithProgress(file, '/api/upload', (percent, loaded, total) => {
  progressBar.value = percent;
  statusText.textContent = `${percent}% (${formatBytes(loaded)} / ${formatBytes(total)})`;
});

File Download

async function downloadFile(url, filename) {
  const response = await fetch(url);

  if (!response.ok) throw new Error(`Download failed: ${response.status}`);

  const blob = await response.blob();

  // Create download link
  const link = document.createElement('a');
  link.href = URL.createObjectURL(blob);
  link.download = filename;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(link.href); // Clean up memory
}

What's your favorite fetch pattern? Anything I missed?

Follow @armorbreak for more JavaScript content.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Mastering the Fetch API: Practical Patterns for Real-World Apps

Thematisch verwandte Begriffe: Mastering, Fetch, Practical, Patterns · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-93987 | rclone versions 1.56.0 through 1.75.0 contain a path traversal vulnerabi…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick