İçeriğe geç
edumintsBlog
Veri Bilimi3 dk okuma

Fetch İsteğini İptal Etmek Node.js Sunucunuzu Durdurmaz: İşte Gerçekten Durduran Yöntem

Kaynak: dev.to

Paylaş
İçindekiler 4 başlık

Frontend tarafında bir kullanıcı filtre değiştirdiğinde veya sayfadan ayrıldığında controller.abort() çağırmak yaygın bir reflekstir. Ancak istemci tarafındaki bu iptal işlemi, arka planda sunucunuzun yürüttüğü iş yüküne otomatik olarak ulaşmaz.

Gerçekleştirilen testte, her biri 200 ms süren 5 adımlı (toplam 100 adımlık) bir Node.js işleyicisine 20 istek gönderilmiş ve istemcilerin 100 ms sonra bağlantıyı kesmesi sağlanmıştır. Sonuç geliştiriciler açısından oldukça düşündürücüdür: Sunucu, artık yanıtı beklemeyen istemciler için 100 adımın 100'ünü de tamamlamıştır. Ancak işleyiciye bağlantı kopmasını dinlemesi öğretildiğinde, aynı 20 istek için 100 adımdan 0'ı çalıştırılmıştır. node:http, Express 4/5, Hono ve PostgreSQL ortamında yapılan testler 3 şaşırtıcı sonucu ortaya koymuştur:

  • node-postgres { signal } seçeneğini sessizce yoksaydı: Parametre verilmesine rağmen sorgu veritabanında çalışmaya devam etti.
  • req.signal Node 24 üzerinde mevcutken Node 22 üzerinde tanımsızdır (undefined): Herhangi bir uyarı olmaksızın bu sürüm farkı oluştu.
  • Postgres iptalini normal bağlantı havuzu (pool) üzerinden göndermek havuzu kilitleyebilir: Yanlış yönetim bağlantı havuzunun askıda kalmasına yol açtı.

İptal Sinyali Nerede Durur?#

Bir istemci isteği iptal ettiğinde süreç şu basamaklarla ilerler:

  • client abort(): Fetch reddedilir, istemci tarafında bağlantı kapanır (otomatik).
  • Sunucu kapanan soketi görür: Soketin kapandığı algılanır (otomatik).
  • İşleyiciniz (handler) çalışmaya devam eder: Kod yazılmadıkça işlem süreci durmaz.
  • Başka bir API'ye yapılan fetch çalışmaya devam eder: Sunucunun dış istekleri kesilmez.
  • SQL sorgusu çalışmaya devam eder: Veritabanı sorgusu sonlanmaz.

Bu zincirde yalnızca ilk iki satır kendiliğinden gerçekleşir; geri kalanın tamamı geliştiricinin yönetmesi gereken kod bloklarıdır. (Senkron CPU döngüleri ise bu kapsam dışında özel bir durumdur.)

İstemci İptal Ettiğinde Sunucu Ne Görür?#

500 ms'lik 5 adımdan oluşan bir işleyicide istemci 1200. ms'de işlemi iptal ettiğinde; istemci 7 ms içinde süreci sonlandırdı. Sunucu yanıtı close olayı yaymasına rağmen, işleyici yalnızca asenkron bir fonksiyon olduğundan durmadı; 3, 4 ve 5. adımlar ölü bir sokete karşı tamamlandı ve res.end() hata dahi fırlatmadı.

Node.js'te İstemcinin Ayrıldığını Yakalamak#

  • Yanıt nesnesindeki (res) close olayını dinleyin.
  • Normal tamamlanma ile erken iptali ayırt etmek için res.writableFinished değerini kontrol edin (normal yanıtta true, iptalde false).
  • req nesnesinin close olayına güvenmeyin; dokümantasyon bunun yalnızca isteğin tamamlandığını garanti eder.

Pratik Mimari Çıkarım#

Sunucu kaynaklarını boşa harcamamak adına istemcinin ayrılmasını bir sunucu zaman aşımıyla birleştiren bir yardımcı fonksiyon kurgulanmalıdır:

export function requestSignal(res, { timeoutMs } = {}) {
  const gone = new AbortController();
  res.once("close", () => {
    if (!res.writableFinished) gone.abort(new Error("client closed request"));
  });
  const signals = [gone.signal];
  if (timeoutMs) signals.push(AbortSignal.timeout(timeoutMs));
  return AbortSignal.any(signals);
}

Oluşturulan bu sinyali (const signal = requestSignal(res, { timeoutMs: 600 });) sinyal kabul eden tüm veritabanı veya dış API çağrılarına ileterek gereksiz sunucu maliyetlerinin önüne geçebilirsiniz.

Kaynak ve atıf

Bu yazı, dev.to üzerinde yayımlanan içerikten yararlanılarak Edumints tarafından yapay zekâ desteğiyle Türkçe hazırlandı. Ayrıntılar ve yazarların kendi anlatımı için orijinaline bakabilirsin:

  • dev.to/shubhradev/aborting-a-fetch-doesnt-stop-your-nodejs-server-heres-what-does-2fek