JAVASCRIPT’IN TARIHÇESI

Promise-2 (Callback, Async, EventEmiter)

Callback, Callback Hell, Async ve EventEmitter gibi kavramların ne olduğunu nasıl çalıştığını anlatmaya çalışacağım.

--

Bu yazıyı daha önceden yazmış olduğum Javascript’in Tarihçesi yazısının bir devamı olarak yazıyorum. Bir çok kavramı tek bir yazıda ele almanın yaratacağı karmaşıklıktan kaçmak için bu yönteme başvurdum. Bu yazılardaki amacım önceden Javascript’in varolan hangi özelliklerinin yetmediğini ve bu geliştirmeyle neyi hedeflediklerini anlatacağım.

Kısa bir dip not olarak şunuda belirteyim ki, aslında bu konu teknik olarak İşletim Sistemi, Process, Thread, Concurrency, Non Blocking I/O, Async, Concurrency ve Paralellik ve Fonksiyonel programlama gibi bir çok konuyu dokunuyor. Derinlemesine teknik konularıda okumak için bir önceki yazımı Promise-1(Non-Blocking I/O) okumanız faydalı olur. ES6'yla gelen bu özelliğin önceden JS Callback ile olduğunu sonrasında Promise benzeri yapılara neden geçildiğini anlatacağım.

Özetle

  • Temel Gereksinimler ve Temel Kavramlar?
  • Callback nedir? Callback Handling Nasıl Gerçekleşir?
  • Callback Hell nedir? Neden sorun oluşturuyor?
  • Callback Hell Çözmek İçin Kullanılan Async Kütüphanesi ve EventEmitter Tasarım Örüntüsü

1. Temel Gereksinimler ve Temel Kavramlar?

Uygulamadan uygulamaya farklı ihtiyaçlar olsada hepsinde arka arkaya çalışan yani CPU, Memory arasında çalışan bir kod bloğu olsada işler hep bu şekilde gerçekleşmez. Sizin I/O işlemi yapmanız gerekir. Nedir bu I/O işlemleri

  • Kullanıcı girdilerinin beklenmesi (Keyboard, Mouse, vb)
  • Dosya erişimi (FileSystem Access)
  • Network erişimi.
  • Ekran Kartı Erişimi.

İlk önce bu I/O işlemlerinin nasıl yapılacağı, nasıl ele alınanacağını anlamamız gerekiyor çünkü .

Browser/Mobile → WebApp: Tarayıcıların kullanıcı girdilerini algılaması bu istekler doğrultusunda Asenkron çalışan Rendering, Kullanıcı Girdilerinin alınması, Network sunucuya istek ve sonucun gelmesini bekleme gibi kısımlar bulunur. Bu konunun detaylarını (Browser’lar Nasıl Çalışır? , Non-Blocking I/O Rest Supported Mobile/Web Frameworks) yazılarımdan bakabilirsiniz.

2. Callback Nedir? Callback Handling Nasıl Gerçekleşir?

Senkron koda bir bakalım.

console.log("Sync1");
console.log("Sync2");
console.log("Sync3");
//Output => Sync1 , Sync2, Sync3

Asenkron koda bir bakalım. Burda timeout ile beklettiğim kısımda local bir dosyaya veya network üzerinden başka bir servise veya veritabanına çağrı yapıyor olabilirsiniz. Aşağıdaki kodda gördüğünüz gibi kodu yazdığınız sırada kod çalışmıyor.

console.log("Async1");
setTimeout(()=>{ console.log("Async2");},1000);
console.log("Async3");
//Output => Async1 , Async3, Async2

Burda 2 tip problem oluşuyor geliştiriciler için kodun işletilme takibi ve kodun okunması ve anlaşılması zorlaşıyor.

Callback sizin asenkron kod çağrımınız bittikten sonra asenkron kodun bittiğini geri bildiren kısmın handle edilmesidir.

const waitThenCall = (waitTime, callback) => {
const result="success";
setTimeout(() => { callback(result) }, waitTime * 1000)
}
waitThenCall(2,(result)=>{console.log(result);});

3. Callback Hell Nedir? Callback Neden Sorun Oluşturuyor?

Callback Hell ise bu asenkron çalışmaların çok fazla olduğu birbiri ardından veya beraber çalışma ihtiyacı olduğu durumda kodunuz giderek iç içe girmiş şekilde Callback yığınlarının olduğu bir yapıya dönüşüyor. Buna Callback Hell deniyor. Bu durumu aşağıdaki örnektede görebilirsiniz Kodun giderek okunamaz hale geldiğini görebilirsiniz.

const waitThenCall = (waitTime, callback) => {
setTimeout(() => { callback() }, waitTime * 1000)
}
waitThenCall(1, () => {
console.log("After1 Seconds")
waitThenCall(2, () => {console.log("After2 Seconds")
waitThenCall(3, () => {console.log("After3 Seconds")
waitThenCall(4, () => {console.log("After4 Seconds")
waitThenCall(5, () => {console.log("After5 Sec")})
})
})
})
})

Callback Hell callback sayısının çok olduğu iç içe olduğu yönetilemediği durumlarda karşımıza çıkar bunun için geliştirilmiş farklı farklı kütüphaneler ve tasarım örüntüleri bulunmaktadır.

4. Callback Hell Çözmek İçin Kullanılan Async Kütüphanesi ve EventEmitter Tasarım Örüntüsü

A. Async Kütüphanesi

Async Kütüphanesi . Bu kütüphane size size Async işlemlerinizi serial veya paralel olarak işletmenizde bir takım kolaylıklar sunar. Örneğin aşağıdaki gibi waterfall şeklinde kodunuzu işletmek istiyorsunuz

Waterfall Execution

Aşağıdaki örnekte yeşil alanlar yazdığımız fonksiyonlar. Hepside async gerektiren yani bir file, network giden fonksiyonlar. Bu fonksiyonların birincisinin çıktısını diğerine geçirerek fonksiyonların çıktısını diğer fonksiyonun kullanmasını sağlıyoruz

En son metoda geldiğimizde de callback(null, ‘done’); çağrımını yaparak fonksiyonu sonlandırıyoruz.

Aşağıdaki örnektede görebileceğiniz gibi içi içe callback yazmanıza gerek yok hepsi aynı seviyede function bir array içerisinde çağırabilmenize olanak sağlıyor bu kütüphane.

async.waterfall

B. Event Emitter Kullanmak

Diğer bir yöntemde EventEmitter kulanmak. Aslında basitçe Observer Pattern. Emitter’den türeyen bir Obje oluşturduğumuzda elimizde event fırlatmak yeteneğine sahip bir objemiz olur.

EventEmitter Tanımlama

Burda elimizde obje üzerinden bir eventId(rfc822Loaded) ve beraberinde istediğimiz parametreler ile this.emit() ile event fırlatılabilir.

Event Fırlatıma

Fırlatılan Eventi yakalamak için aşağıdaki gibi .on fonksiyonu bağlayıp event dinleyebilirsiniz.

Fırlatılan Eventi yakalayıp işletmek için callback

Bu tasarım bir çok sorunu çözüyor fakat çok fazla olan eventlerde akışı görüntülemek ve takibi oldukça zor hale geliyor. Ama benim en çok beğendiğim kodun temiz olmasını sağlayan yöntemlerden bir taneside bu.

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--