İçeriğe geç
academia.sh

Ders 06 / 17

Söz Birleştiricileri

Birden çok sözü tek sözde toplayan dört birleştirici; hata karşısındaki davranış farkları; işin ne zaman başladığı ile ne zaman beklendiğinin ayrımı.

İçindekiler

Önceki ders tek bir sözü bir değer haline getirdi. Değer olan şey diziye konabilir; diziye konan şey topluca ele alınabilir. Geri çağrı konusunda sayaç ve bayrakla elle yazılan “hepsini bekle” işlevi, artık dilin sağladığı bir işleçle yazılabilir.

Bu ders dört birleştiriciyi tanıtır ve aralarındaki asıl farkın hata karşısındaki davranış olduğunu gösterir. Ölçüm akışı burada üç istasyonu birlikte okuyan bir toplayıcıya dönüşür.

İş Ne Zaman Başlar

Birleştiricileri doğru okumak için önce bir yanlış anlamanın giderilmesi gerekir: birleştiriciler işi başlatmaz. İş, sözler oluşturulduğunda başlamıştır; birleştirici yalnız beklemeyi düzenler.

Aşağıdaki örneklerde ölçüm kaynağı, isteğin başladığı anı da yazdırır. Kurs boyunca kullanılan tablo, arızalı D4 istasyonunu da içerir.

const KAYNAK = {
  A1: { gecikme: 30, deger: 21.4 },
  B2: { gecikme: 10, deger: 19.8 },
  C3: { gecikme: 20, deger: 23.1 },
  D4: { gecikme: 15, hata: "sensör arızası" },
};

function olcumGetir(istasyon) {
  console.log("istek başladı:", istasyon);
  return new Promise((karar, red) => {
    const kayit = KAYNAK[istasyon];
    setTimeout(() => {
      if (kayit.hata) red(new Error(`${istasyon}: ${kayit.hata}`));
      else karar({ istasyon, deger: kayit.deger });
    }, kayit.gecikme);
  });
}

const olcumler = await Promise.all([olcumGetir("A1"), olcumGetir("B2"), olcumGetir("C3")]);
console.log("sonuç:", olcumler.map((o) => `${o.istasyon}=${o.deger}`).join(" "));
istek başladı: A1
istek başladı: B2
istek başladı: C3
sonuç: A1=21.4 B2=19.8 C3=23.1

Üç istek de Promise.all çağrılmadan önce, dizi hazırlanırken başladı. Beklemeler üst üste bindi; sonuç, en yavaş istek olan A1 tamamlandığında geldi.

Sonuç dizisi istek sırasını korur, geliş sırasını değil. Geri çağrı konusunda bunu sağlamak için sonuçları dizine göre yerleştirmek gerekiyordu; burada güvence birleştiricinin kendisindedir.

Hepsini Bekle: Promise.all

Promise.all, verilen sözlerin tümü yerine geldiğinde, sonuç dizisiyle yerine gelir. Herhangi biri reddedilirse, ilk reddetmeyle birlikte hemen reddedilir.

const KAYNAK = {
  A1: { gecikme: 30, deger: 21.4 },
  B2: { gecikme: 10, deger: 19.8 },
  C3: { gecikme: 20, deger: 23.1 },
  D4: { gecikme: 15, hata: "sensör arızası" },
};

function olcumGetir(istasyon) {
  console.log("istek başladı:", istasyon);
  return new Promise((karar, red) => {
    const kayit = KAYNAK[istasyon];
    setTimeout(() => {
      if (kayit.hata) red(new Error(`${istasyon}: ${kayit.hata}`));
      else karar({ istasyon, deger: kayit.deger });
    }, kayit.gecikme);
  });
}

try {
  await Promise.all([olcumGetir("A1"), olcumGetir("D4"), olcumGetir("C3")]);
} catch (hata) {
  console.log("all reddedildi:", hata.message);
}
istek başladı: A1
istek başladı: D4
istek başladı: C3
all reddedildi: D4: sensör arızası

İki nokta önemlidir. Birincisi, sonuç on beşinci milisaniyede belli oldu; A1 ve C3 beklenmedi. İkincisi ve daha önemlisi: beklenmemek, iptal edilmek değildir. A1 ve C3 istekleri sürmeye devam eder, sonuçları da üretilir; yalnız kimse onlara bakmaz. İptal ayrı bir düzenek gerektirir ve ilerideki bir derste kurulacak.

Bu davranış, “hepsi olmazsa hiçbiri” anlamı taşıyan işler için doğrudur: üç ölçümün ortalaması, biri eksikken hesaplanamaz.

Hepsinin Sonucunu Topla: Promise.allSettled

Kısmi sonuç kabul edilebilir olduğunda all yanlış araçtır. Promise.allSettled hiçbir zaman reddedilmez; her söz için durumu ve sonucunu taşıyan bir kayıt döndürür.

const KAYNAK = {
  A1: { gecikme: 30, deger: 21.4 },
  B2: { gecikme: 10, deger: 19.8 },
  C3: { gecikme: 20, deger: 23.1 },
  D4: { gecikme: 15, hata: "sensör arızası" },
};

function olcumGetir(istasyon) {
  console.log("istek başladı:", istasyon);
  return new Promise((karar, red) => {
    const kayit = KAYNAK[istasyon];
    setTimeout(() => {
      if (kayit.hata) red(new Error(`${istasyon}: ${kayit.hata}`));
      else karar({ istasyon, deger: kayit.deger });
    }, kayit.gecikme);
  });
}

const sonuclar = await Promise.allSettled([olcumGetir("A1"), olcumGetir("D4"), olcumGetir("C3")]);
for (const s of sonuclar) {
  if (s.status === "fulfilled") console.log("yerine geldi:", s.value.istasyon, s.value.deger);
  else console.log("reddedildi:", s.reason.message);
}
istek başladı: A1
istek başladı: D4
istek başladı: C3
yerine geldi: A1 21.4
reddedildi: D4: sensör arızası
yerine geldi: C3 23.1

Arızalı istasyon akışı durdurmadı; iki geçerli ölçüm elde edildi ve hata da kaydedildi. Ölçüm ağı gibi kısmi verinin işe yaradığı alanlarda varsayılan seçim budur.

Kayıtların alan adları sabittir: yerine gelmiş kayıtta status ve value, reddedilmiş kayıtta status ve reason bulunur.

İlk Sonuçlanan: Promise.race

Promise.race, hangi söz önce sonuçlanırsa onun sonucunu alır — yerine gelme ile reddetme arasında ayrım yapmaz.

const KAYNAK = {
  A1: { gecikme: 30, deger: 21.4 },
  B2: { gecikme: 10, deger: 19.8 },
  C3: { gecikme: 20, deger: 23.1 },
  D4: { gecikme: 15, hata: "sensör arızası" },
};

function olcumGetir(istasyon) {
  console.log("istek başladı:", istasyon);
  return new Promise((karar, red) => {
    const kayit = KAYNAK[istasyon];
    setTimeout(() => {
      if (kayit.hata) red(new Error(`${istasyon}: ${kayit.hata}`));
      else karar({ istasyon, deger: kayit.deger });
    }, kayit.gecikme);
  });
}

const ilk = await Promise.race([olcumGetir("A1"), olcumGetir("B2"), olcumGetir("C3")]);
console.log("race sonucu:", ilk.istasyon, ilk.deger);

try {
  await Promise.race([olcumGetir("A1"), olcumGetir("D4")]);
} catch (hata) {
  console.log("race reddedildi:", hata.message);
}
istek başladı: A1
istek başladı: B2
istek başladı: C3
race sonucu: B2 19.8
istek başladı: A1
istek başladı: D4
race reddedildi: D4: sensör arızası

İkinci yarışta en hızlı sonuçlanan söz arızalı istasyonunkiydi; race onu da sonuç saydı. Bu nedenle race, “en hızlı sağlıklı yanıtı al” anlamına gelmez.

Bir uyarı gerekir: yarışı kaybeden sözler yaşamaya devam eder. Hiç sonuçlanmayan bir söz race içine konursa, o söz ve kapattığı bütün değerler program boyunca bellekte kalır. Bu, bellek konusunda ele alınacak sızıntı türlerinden biridir.

İlk Başarılı: Promise.any

Promise.any, reddetmeleri yok sayar ve ilk yerine gelen sonucu döndürür. Hepsi reddedilirse, tüm nedenleri içeren bir toplu hatayla reddedilir.

const KAYNAK = {
  A1: { gecikme: 30, deger: 21.4 },
  D4: { gecikme: 15, hata: "sensör arızası" },
};

function olcumGetir(istasyon) {
  console.log("istek başladı:", istasyon);
  return new Promise((karar, red) => {
    const kayit = KAYNAK[istasyon];
    setTimeout(() => {
      if (kayit.hata) red(new Error(`${istasyon}: ${kayit.hata}`));
      else karar({ istasyon, deger: kayit.deger });
    }, kayit.gecikme);
  });
}

const ilkBasarili = await Promise.any([olcumGetir("A1"), olcumGetir("D4")]);
console.log("any sonucu:", ilkBasarili.istasyon, ilkBasarili.deger);

try {
  await Promise.any([olcumGetir("D4")]);
} catch (hata) {
  console.log("any reddedildi:", hata.constructor.name);
  console.log("içindeki hatalar:", hata.errors.map((h) => h.message).join(", "));
}
istek başladı: A1
istek başladı: D4
any sonucu: A1 21.4
istek başladı: D4
any reddedildi: AggregateError
içindeki hatalar: D4: sensör arızası

Arızalı istasyon on beşinci milisaniyede reddetti; any bunu yok sayıp otuzuncu milisaniyedeki geçerli yanıtı bekledi. Toplu hata nesnesi, tek tek nedenleri errors dizisinde taşır — böylece hiçbir hata bilgisi kaybolmaz.

Bu birleştirici, aynı veriyi birden çok kaynaktan isteyip ilk çalışanı kullanan yedeklilik kalıbının doğrudan karşılığıdır.

Seçim Ölçütü

Birleştirici Yerine gelir Reddedilir Uygun olduğu durum
all Hepsi yerine gelirse İlk reddetmede Bütün parçalar zorunlu
allSettled Her zaman Hiçbir zaman Kısmi sonuç kabul edilebilir
race İlk sonuçlanan yerine gelmişse İlk sonuçlanan reddedilmişse Zaman sınırı koymak
any İlk yerine gelende Hepsi reddedilirse Yedekli kaynaklar

Dördü de aynı girdi biçimini alır ve tek bir söz döndürür; bu nedenle iç içe kullanılabilirler. Bir istasyon kümesinin any ile seçilen sonucu, başka bir kümenin sonucuyla all içinde birleştirilebilir.

Özet

  • Birleştiriciler işi başlatmaz; sözler oluşturulduğunda iş başlamıştır, birleştirici yalnız beklemeyi düzenler.
  • all sonuç dizisini istek sırasında verir ve ilk reddetmede hemen reddedilir; beklenmeyen istekler iptal edilmez, sürmeye devam eder.
  • allSettled hiç reddedilmez; her söz için durum ve sonuç kaydı döndürür.
  • race ilk sonuçlanana bakar, başarı ile başarısızlığı ayırt etmez; any ilk yerine geleni seçer ve hepsi reddedilirse nedenleri toplu bir hatada taşır.
  • Yarışı kaybeden ve sonuçlanmayan sözler bellekte kalmaya devam eder.

Sonraki Adım

Birleştiriciler beklemenin yapısını kurdu, ama kodun okunuşunu değiştirmedi: sonuçlar hâlâ geri çağrıların içinde işleniyor. Sonraki ders, aynı zincirleri sıralı bir yazımla ifade eden sözdizimsel katmanı tanıtır — async ve await. Aynı derste, bu yazımın farkında olmadan sıralı beklemeye yol açtığı yaygın hata da gösterilecek ve bu derste kurulan birleştiricilerle düzeltilecek.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat