Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

Bir queue mekanizması tasarlarken `setInterval` yerine recursive `setTimeout` kullanma nedenim ve örnek kodum

asternix

Üye
Katılım
14 Mart 2026
Mesajlar
39
Merhaba arkadaşlar, bugün sizlere bir iş kuyruğu (queue) mekanizması tasarlarken yaşadığım bir optimizasyon hikayesini anlatacağım. Özellikle belirli aralıklarla çalışan, sırayla işlem yapan sistemler kurarken, hepimizin ilk aklına gelen setInterval oluyor değil mi? Ama işler bazen göründüğü gibi olmuyor, ben de bu yüzden kafayı yemiştim!

🔥 Neden setInterval Sorun Çıkarıyor?

Şöyle düşünün: `setInterval` tam bir saat gibi, her X milisaniyede bir tetiklenmeye programlanmış. Peki ya o tetiklenme anında yapması gereken iş (callback fonksiyonu) beklenenden uzun sürerse? İşte tam da burada kuyrukta birikmeler başlıyor. Çünkü interval, işin bitip bitmediğine bakmadan, "zamanı geldi" diye yeni bir iş parçacığı daha ateşliyor. Bu da özellikle ağ istekleri, dosya okuma/yazma gibi değişken süreli işlemlerde callback hell ve bellek tüketimine yol açabiliyor.

Benim senaryomda, bir API'den veri çekip, bu verileri işleyip, sonra bir sonraki API isteğini yapacak bir queue lazımdı. İki istek arasında da sabit bir bekleme süresi olmalıydı. İlk denememde `setInterval` kullandım ve bazen API yavaş cevap verdiğinde, kuyrukta korkunç bir birikme olduğunu gördüm.

🔄 Recursive setTimeout Mantığı

Çözüm olarak, recursive (kendini çağıran) bir `setTimeout` yapısına geçtim. Mantık basit: Bir işi yap, iş BİTTİKTEN SONRA, bir sonraki işin ne zaman başlayacağını hesapla ve timer'ı öyle kur. Bu sayede, önceki işlem ne kadar uzun sürerse sürsün, bir sonraki işlem için geri sayım, ancak o işlem bittikten sonra başlıyor. Kuyrukta hiçbir şekilde birikme olmuyor.

İşte benim basit ve temiz queue sınıfım:

JavaScript:
class SabitAralikliQueue {
  constructor(islemYapFonksiyonu, aralikMs = 1000) {
    this.islemYap = islemYapFonksiyonu;
    this.aralik = aralikMs;
    this.timeoutId = null;
    this.calissin = false;
  }

  // Kuyruğu çalıştırmaya başla
  baslat() {
    if (this.calissin) return;
    this.calissin = true;
    console.log('Queue başlatıldı.');
    this.sonrakiAdimiPlanla();
  }

  // Recursive setTimeout'un kalbi burada
  sonrakiAdimiPlanla() {
    if (!this.calissin) return;

    // İŞİ YAP: API çağrısı, dosya işlemi vs.
    this.islemYap().finally(() => {
      // İş BİTTİ, şimdi bir sonraki iş için timer kur
      if (this.calissin) {
        this.timeoutId = setTimeout(() => {
          this.sonrakiAdimiPlanla(); // Kendini tekrar çağır (Recursive)
        }, this.aralik);
      }
    });
  }

  // Kuyruğu durdur
  durdur() {
    this.calissin = false;
    if (this.timeoutId) {
      clearTimeout(this.timeoutId);
      this.timeoutId = null;
    }
    console.log('Queue durduruldu.');
  }
}

💡 Kullanım Örneği ve Avantajları

Bu queue'yu şöyle kullanabilirsiniz:

JavaScript:
// Örnek bir işlem fonksiyonu (Örn: Bir API'ye istek at)
async function ornekIslem() {
  console.log(`[${new Date().toISOString()}] İşlem başlıyor...`);
  // Simüle edilmiş değişken süreli iş (0-3 saniye arası)
  const bekleme = Math.random()  3000;
  await new Promise(resolve => setTimeout(resolve, bekleme));
  console.log(`İşlem tamamlandı (${bekleme.toFixed(0)}ms sürdü).`);
}

// Saniyede 1 işlem yapması için queue oluştur
const benimKuyrugum = new SabitAralikliQueue(ornekIslem, 1000);

// Kuyruğu başlat
benimKuyrugum.baslat();

// 10 saniye sonra durdur (örnek amaçlı)
setTimeout(() => benimKuyrugum.durdur(), 10000);

Bu yapının en büyük avantajı, işlemlerin asla üst üste binmemesi. Konsol çıktısına bakarsanız, bir işlem 2.5 saniye de sürse, bir sonraki işlem onun bitiminden tam 1 saniye sonra başlayacak. `setInterval` kullansaydık, aynı 2.5 saniyelik işlem sırasında 2 yeni işlem daha tetiklenmeye çalışılacak ve kuyruk şişecekti.

Sonuç olarak, özellikle async/await veya Promise kullandığınız, süresi öngörülemeyen işlemleriniz varsa, recursive `setTimeout` bence çok daha sağlam ve temiz bir çözüm. Siz daha önce böyle bir queue mekanizması tasarladınız mı? `setInterval` ile başınız dertte oldu mu? Ya da bu pattern için ekleyeceğiniz farklı bir öneriniz var mı? Yorumlarda paylaşalım!
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Geri