Görselleştirilmiş JavaScript: Event Loop

Gizem Korkmaz
4 min readMay 3, 2022

--

Bu yazı Lydia Hallie’nin JavaScript Visualized: Event Loop adlı makalesinin bir çevirisidir.

Ah, event loop (olay döngüsü)! Bu, her JavaScript geliştiricisinin bir şekilde uğraşmak zorunda olduğu şeylerden biri ancak ilk zamanlar anlaşılması biraz kafa karıştırıcı olabilir. Ben görseller ile öğrenen biriyim, bu yüzden düşük çözünürlüklü giflerle (2019 yılındayız ve gifler bir şekilde hala pikselli ve bulanık) görsel olarak açıklayarak size yardımcı olabileceğimi düşündüm.

Öncelikle event loop nedir ve neden önemsemelisiniz?

JavaScript single-threaded bir dildir. Yani eş zamanlı olarak yalnızca tek bir görev çalıştırabilir. Bu çoğunlukla bir sorun teşkil etmez ancak 30 saniye süren bir görev düşünün… Aynen öyle… Bu görev esnasında başka hiçbir şey olmadan 30 saniye boyunca bekliyoruz (JavaScript, tarayıcının ana thread’inde varsayılan olarak çalışır ve böylece tüm arayüz tıkanır 😬). 2019 yılında kimse böyle yavaş ve yanıt vermeyen bir web sitesi istemiyordur.

Neyse ki tarayıcı bize JavaScript motorunun sağlamadığı bazı özellikler sunuyor: bir Web API’ı. Buna DOM API, setTimeout, HTTP istekleri vs. de dahildir. Bu da bize asenkron, non-blocking (tıkanmasız) işlemler yapmamıza yardımcı olabilir 🚀

Bir fonksiyonu çağırdığımızda fonksiyon call stack adı verilen bir şeye eklenir. Call stack, JS motorunun bir parçasıdır, taracıya özgü bir şey değildir. Bu bir stack’tir (yığın) yani ilk eklenen son çıkar (bir pankek yığınını düşünün). Fonksiyon bir return değeri döndüğünde stack’ten atılır 👋

1 || Fonksiyonlar çağırıldıklarında call stack’e eklenir, bir değere döndüklerinde ise çıkarılırlar.

Yukarında respond fonksiyonu bir setTimeout fonksiyonu dönüyor. setTimeout bize Web API tarafından temin edilir. Ana thread’i tıkamadan görevleri geciktirmemize yardımcı olur. setTimeout fonksiyonuna eklediğimiz callback olan () => { return ‘Hey' } fonksiyonu Web API’ına eklenir. Bu esnada setTimeout fonksiyonu ve respond fonksiyonu stack’ten atılır, her ikisi de return değerlerine dönmüşlerdir!

2 || setTimeout browser tarafından sağlanır ve ona gönderdiğimiz callback ile Web API ilgilenir.

Web API’ında timer, ilettiğimiz ikinci argüman olan 1000 ms boyunca çalışır. Callback hemen call stack’e eklenmez, bunun yerine queue (sıra) adı verilen bir şeye eklenir.

3 || timer tamamlandığında (mevcut durumda 1000 ms sonunda) callback, callback sırasına gönderilir.

Şu biraz kafa karıştırıcı olabilir: callback fonksiyonunun call stack’e 1000 ms sonunda eklendiği (ve böylece bir return değeri döndürdüğü) anlamına gelmiyor! Sadece 1000 ms sonunda queue’ya (sıraya) alınıyor ve fonksiyon sırasını beklemek zorunda kalıyor!

Ve hepimizin beklediği o kısım… Event loop’un yapması gereken tek görevinin zamanı geldi: call stack ile queue’yu birleştirme! Eğer call stack boşsa, yani önceden çağırılan fonksiyonların hepsi return değerlerine döndüler ve stack’ten temizlendilerse, sıradaki ilk işlem maddesi call stack’e eklenir. Bu durumda başka hiçbir fonksiyon çağırılmaz, yani callback fonksiyonu sıradaki ilk işlem maddesi olduğu zamanda call stack temizlenmiştir.

4 || Event loop, callback sırasına ve call stack’e bakar. Eğer call stack boşsa sıradaki ilk işlem maddesini stack’e gönderir.

Callback, call stack’e eklenmiş, çağırılmış, return değerine dönmüş ve stack’ten çıkarılmıştır.

5 || Callback, call stack’e eklenir ve çalıştırılır. Bir değere döndüğünde ise call stack’ten çıkarılır.

Makale okumak da keyiflidir ama üzerine ancak tekrar tekrar çalışarak bunları iyice sindirebilirsiniz. Aşağıdaki kodu çalıştırdığımızda konsola ne yazdırılıcağını tahmin etmeye çalışın:

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"), 500);
const baz = () => console.log("Third");

bar();
foo();
baz();

Tamam mıyız? Haydi kodu tarayıcıda çalıştırarak hızlıca neler olduğuna bir göz atalım:

  1. bar fonksiyonu çağırılır. bar bir setTimeout fonksiyonu döner.
  2. setTimeout’a eklediğimiz callback Web API’ına eklenir, setTimeout ve bar fonksiyonları call stack’ten çıkarılır.
  3. Timer çalışır, bu esnada foo çağırılır ve konsola First yazdırılır. foo return değerine döner (undefined), baz fonksiyonu çağırılır ve callback sırasına eklenir.
  4. baz konsola Third yazdırır. Event loop, baz return değerine döndükten sonra call stack’in boş olduğunu görür ve böylece callback, call stack’e eklenir.
  5. Callback konsola Second yazdırır.

Umarım bu yazı event loop konusunda biraz daha rahat olmanızı sağlamıştır! Hala kafa karıştırıcı geliyorsa endişelenmeyin, önemli olan belirli hataların/davranışların nereden geldiğini anlayabilmek ve böylece Google’da doğru terimleri verimli şekilde araştırıp doğru Stack Overflow sayfasını bulabilmek 💪🏼

Herhangi bir sorunuz olduğunda iletişime geçmekten çekinmeyin!

--

--