Merhaba, bu yazımda sizlere JavaScript ile ilgilenen geliştiricilerin en az bir kere karşılaşmış olduğu Call Stack ve Event Loop konularından bahsedeceğim.
CallStack
JavaScript single-thread(tek iş parçacıklı) bir dildir, yani tek bir call stack olduğundan aynı anda tek bir iş yapabilir. JavaScript motorları (Chrome V8 gibi) execution context`i yönetmek için Call Stack’i kullanır. Buradaki işlemler LIFO principle (Last In, First Out) yani son giren ilk çıkar stack’de en üstteki çağrı ilk işlenir.
- Memory Heap: Oluşturduğumuz değişkenlerin, objelerin, fonksiyonların tutulduğu alan.
- Web APIs: JavaScript için single-tread çalışıyor demiştik ancak aynı anda birkaç şey yapmak istiyorsak bu tarayıcıların sağladığı WEB API’lar sayesinde mümkün oluyor. Yani asenkron bir işlem yapmak istediğimizde, bir API isteği yaptığımızda bu kendi tread’ı içerisinde yapılıyor ve Callback Queue’ya aktarılıyor. Örnek olarak setTimeout ile 1 saniye sonra konsola “hello” yazmak istiyoruz. Bu durumda ilk olarak setTimeout() fonksiyonu stack’e eklenecek, burada 1 saniyelik işlem olduğundan buradaki callback fonksiyonu WEB APIs’a eklenecek ve stack’den setTimeout kaldırılacak. Yani stack boş ve kod bloklanmıyor 1 saniye sonra WEB APIs’daki callback fonksiyon Callback queue’ya eklenecek event loop stack boş ise bu callback fonksiyonu stack’e ekleyecek.
- Callback Queue: WEB API’da yaptığımız asenkron işlem tamamlanınca, callback buraya düşüyor.
- Event Loop: Call stack boş olur olmaz, Callback queue‘daki ilk çağrıyı call stack’e ekliyor.
Yukarıdaki kodda üç fonksiyon oluşturdum. 1. foo isimli fonksiyon konsola “foo” yazacak. 2. bar isimli fonksiyon konsola “bar” yazacak. 3. hello isimli fonksiyon içerisinde foo ve bar fonksiyonlarını çağırıp sonrasında konsola “hello” yazdırdım ve en son hello() fonksiyonunu çağırdım.
function foo(){
console.log("foo");
}
function bar(){
console.log("bar");
}
function hello(){
foo();
bar();
console.log ("hello");
}
hello();
Kod yukarından aşağı okunuyor.
- İlk olarak hello() fonksiyonu Call Stack‘e ekleniyor
- içerisinde foo() fonksiyonu çağırılmış o da call stack’e ekleniyor, foo fonksiyonu konsola “foo” yazması gerekiyor bunu da call stack’e ekliyor. Ne demiştik L.I.F.O (last in, first out) son giren ilk çıkar yani son giren console.log bu yürütülüp stack’den çıkıyor. foo fonksiyonu da daha başka bir iş yapmadığı için stack’den kaldırılıyor.
- hello fonksiyonu hala stack’de çünkü daha işi bitmedi. Şimdi bar fonksiyonu call stack‘e ekleniyor, konsola “bar” yazması gerekiyor bunu da stack’e ekliyor, yürütülüp ve aynı foo gibi stack’den kaldırılıyor.
- Son olarak hello fonksiyonu konsola “hello” yazmalı stack’e ekleniyor konsola “hello” yazıyor ve stack’den çıkıyor. hello fonksiyonu daha başka bir iş yapmıyor o da stack’den kaldırılıyor.
Asenkron İşlem
Son olarak setTimeout ile bir örnek inceleyelim.
console.log("hello");
function world(){
console.log("world")
}
setTimeout(function cbFunction(){
console.log("Callback Function")
}, 1000);
world();
- Yukarıdaki kodda ilk satır call stack‘e ekleniyor ve konsola “hello” yazıyor sonra stack’den çıkıyor.
- Hemen altında konsola “world” yazan bir world adında fonksiyon var. Bu fonksiyon setTimeout sonrasında çağırılmış.
- Bu durumda setTimeout fonksiyonunu stack’e ekleniyor ve bakılıyor 1000 milisaniyelik işlem var buradaki callback fonksiyonu yani cbFunction() isimli fonksiyonu WEB API‘a ekliyor burada 1000 ms beklerken setTimeout stack’den kaldırılıyor.
- Ardından ilk olarak en alt satırdaki world() fonksiyonunu sonrasında console log’u call stack’e ekliyor bunlar yürütülüp stack’den kaldırılıyor bu sırada 1000ms geçiyor ve cbFunction() Callback queue‘ya eklendi.
- Event Loop, call stack boş ise bu fonksiyonu stack’e ekleyip konsola “Callback Function” yazıyor ve stack’den kaldırılıyor, bu fonksiyonda başka iş yapmadığı için stack’den çıkıyor sonuç olarak call stack yine boş kalıyor.
Kaynaklar