Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Linux Tipps & HardeningSecurity: Zwei Probleme in freeciv (Fedora)(19.09.2026 um 10:49 Uhr)
Linux Tipps & HardeningSecurity: Denial of Service in stb (Fedora)(19.09.2026 um 10:49 Uhr)
Linux Tipps & HardeningSecurity: Ausführen beliebiger Kommandos in evolution (Fedora)(19.09.2026 um 10:49 Uhr)
Linux Tipps & HardeningSecurity: Mehrere Probleme in libheif (Fedora)(20.09.2026 um 08:47 Uhr)
Sichere ProgrammierungBuilding a REST API Client with Java HttpClient + Jackson(20.09.2026 um 07:43 Uhr)
Sichere ProgrammierungThe Story: Liberating Kannada’s Beauty from the ASCII Trap(20.09.2026 um 07:45 Uhr)
Sichere ProgrammierungGemini Hacked Three Companies Using the Dumbest Trick in the Book(20.09.2026 um 07:50 Uhr)
Sichere ProgrammierungWhat Automated Slow-3G Testing Reveals About Frontend Assumptions(20.09.2026 um 07:54 Uhr)
Sichere ProgrammierungHow I Structure MiniMax H3 Max Image-to-Video Prompts with Sound(20.09.2026 um 07:54 Uhr)
Linux Tipps & HardeningSecurity: Zwei Probleme in freeciv (Fedora)(19.09.2026 um 10:49 Uhr)
Linux Tipps & HardeningSecurity: Denial of Service in stb (Fedora)(19.09.2026 um 10:49 Uhr)
Linux Tipps & HardeningSecurity: Ausführen beliebiger Kommandos in evolution (Fedora)(19.09.2026 um 10:49 Uhr)
Linux Tipps & HardeningSecurity: Mehrere Probleme in libheif (Fedora)(20.09.2026 um 08:47 Uhr)
Sichere ProgrammierungBuilding a REST API Client with Java HttpClient + Jackson(20.09.2026 um 07:43 Uhr)
Sichere ProgrammierungThe Story: Liberating Kannada’s Beauty from the ASCII Trap(20.09.2026 um 07:45 Uhr)
Sichere ProgrammierungGemini Hacked Three Companies Using the Dumbest Trick in the Book(20.09.2026 um 07:50 Uhr)
Sichere ProgrammierungWhat Automated Slow-3G Testing Reveals About Frontend Assumptions(20.09.2026 um 07:54 Uhr)
Sichere ProgrammierungHow I Structure MiniMax H3 Max Image-to-Video Prompts with Sound(20.09.2026 um 07:54 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