Pattern Retry dan Timeout untuk Async JavaScript Production-Ready
Taufiq M
Taufiq M

Dipublikasikan 24 Mei 2026

Pattern Retry dan Timeout untuk Async JavaScript Production-Ready

Async programming di JavaScript sudah jadi standar, tapi banyak code yang masih rentan terhadap network failure dan timeout. Tutorial dari DaniKeya di Dev.to menunjukkan bahwa dua function sederhana saja bisa membuat async code production-ready. Artikel ini akan membahas implementasi pattern retry dan timeout untuk async JavaScript.

Langkah 1: Kenapa Retry dan Timeout Penting

Network tidak selalu reliable. API bisa down sementara, connection bisa timeout, atau rate limit bisa mengembalikan error sementara. Tanpa retry, aplikasi kamu akan langsung gagal. Tanpa timeout, aplikasi bisa menunggu response yang tidak pernah datang.

Dua function yang akan kita bangun adalah retry dan timeout. Function ini reusable dan bisa di-attach ke async operation apa pun.

Langkah 2: Implementasi Function Timeout

Function timeout memberikan batas waktu eksekusi pada async operation. Jika operation melebihi batas waktu, Promise akan reject dengan error timeout.

function timeout(promise, ms) {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      reject(new Error('Operation timed out'));
    }, ms);
    promise.then((value) => {
      clearTimeout(timer);
      resolve(value);
    }).catch((error) => {
      clearTimeout(timer);
      reject(error);
    });
  });
}

Penggunaannya sederhana: bungkus Promise dengan timeout wrapper.

const result = await timeout(fetchUserData(), 5000);

Jika fetchUserData tidak selesai dalam 5 detik, Promise akan reject.

Langkah 3: Implementasi Function Retry dengan Exponential Backoff

Retry tidak cukup hanya dengan mengeksekusi ulang. Kita perlu exponential backoff untuk menghindari thundering herd problem dan memberikan waktu bagi service untuk recover.

async function retry(fn, { retries = 3, delay = 1000, backoff = 2 } = {}) {
  try {
    return await fn();
  } catch (error) {
    if (retries === 0) throw error;
    await new Promise(resolve => setTimeout(resolve, delay));
    return retry(fn, { retries: retries - 1, delay: delay * backoff, backoff });
  }
}

Function ini secara rekursif memanggil operation dengan delay yang meningkat secara eksponensial. Parameter retries, delay, dan backoff bisa dikustomisasi sesuai kebutuhan.

const result = await retry(() => fetch('/api/data'), {
  retries: 5,
  delay: 1000,
  backoff: 2
});

Langkah 4: Komposisi Retry dan Timeout

Timeout dan retry paling powerful ketika digunakan bersamaan. Retry akan menangani transient failures, sementara timeout mencegah operation terjebak terlalu lama.

async function fetchWithRetryAndTimeout(url, options = {}) {
  const { retries = 3, timeoutMs = 5000 } = options;
  return retry(
    () => timeout(fetch(url), timeoutMs),
    { retries, delay: 1000, backoff: 2 }
  );
}

Function ini memberikan 3 kali retry dengan exponential backoff, dan setiap attempt dibatasi 5 detik. Ini adalah pattern yang sangat umum di production code.

Langkah 5: Integrasi ke Project React/Vue/Next.js

Pattern ini bisa di-extract menjadi custom hook atau utility module. Berikut contoh custom hook untuk React:

import { useState, useEffect } from 'react';

function useAsyncWithRetry(fn, deps, options = {}) {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    async function execute() {
      try {
        const result = await retry(() => timeout(fn(), options.timeout || 5000), {
          retries: options.retries || 3,
          delay: 1000,
          backoff: 2
        });
        if (!cancelled) setData(result);
      } catch (err) {
        if (!cancelled) setError(err);
      } finally {
        if (!cancelled) setLoading(false);
      }
    }
    execute();
    return () => { cancelled = true; };
  }, deps);

  return { data, error, loading };
}

Custom hook ini menangani cleanup saat component unmount, sehingga tidak ada state update pada component yang sudah tidak ada.

Kesimpulan

Pattern retry dan timeout adalah fondasi untuk async code yang resilient di production. Dengan hanya dua function kecil, kamu sudah bisa menangani transient failures dan prevent hanging operations. Source lengkap dan penjelasan detail bisa dilihat di tutorial asli Dev.to - Retry dan Timeout Functions.