diff --git a/2-ui/99-ui-misc/03-event-loop/article.md b/2-ui/99-ui-misc/03-event-loop/article.md new file mode 100644 index 000000000..26a80afe9 --- /dev/null +++ b/2-ui/99-ui-misc/03-event-loop/article.md @@ -0,0 +1,341 @@ + +# Olay döngüsü: microtasks ve macrotasks + +Node.js'de olduğu gibi tarayıcı JavaScript yürütme akışı da bir *olay döngüsüne* dayanır. + +Olay döngüsünün nasıl çalıştığını anlamak, optimizasyonlar ve bazen de doğru mimari için önemlidir. + +Bu bölümde önce işlerin nasıl yürüdüğüyle ilgili teorik ayrıntıları ele alacağız ve ardından bu bilginin pratik uygulamalarını göreceğiz. + +## Olay Döngüsü + +*Olay döngüsü* kavramı çok basittir. JavaScript motorunun görevleri beklediği, yürüttüğü ve daha sonra uyuyarak daha fazla görev beklediği sonsuz bir döngü vardır. + +Motorun genel algoritması: + +1. Görevler varken: + - en eski görevden başlayarak bunları yürütün. +2. Bir görev görünene kadar uyuyun, ardından 1'e gidin. + +Bu, bir sayfaya göz atarken gördüğümüz şeyin biçimselleştirilmesidir. JavaScript motoru çoğu zaman hiçbir şey yapmaz, yalnızca bir script/işleyici/olay etkinleştirildiğinde çalışır. + +Görev örnekleri: + +- Harici bir script ` +``` + +...Ancak görev sırasında da bir şey göstermek isteyebiliriz, örneğin bir ilerleme çubuğu. + +Eğer ağır görevi `setTimeout` kullanarak parçalara ayırırsak, o zaman değişiklikler aralarında boyanır. + +Bu daha güzel görünüyor: + +```html run +
+ + +``` + +Şimdi `
`, bir tür ilerleme çubuğu olan `i`'nin artan değerlerini gösteriyor. + + +## Kullanım Senaryosu 3: olaydan sonra bir şeyler yapmak + +Bir olay işleyicide, bazı eylemleri olay kabarıp tüm seviyelerde işlenene kadar ertelemeye karar verebiliriz. Bunu, kodu sıfır gecikmeli `setTimeout` içine sararak yapabiliriz. + + bölümünde bir örnek gördük: `menu-open` özel olayı(custom event) `setTimeout` içinde gönderilir, böylece "click" olayı tamamen işlendikten sonra gerçekleşir. + +```js +menu.onclick = function() { + // ... + + // tıklanan menü öğesi verileriyle özel bir olay oluşturun + let customEvent = new CustomEvent("menu-open", { + bubbles: true + }); + + // özel olayı eşzamansız(asynchronously) olarak gönder + setTimeout(() => menu.dispatchEvent(customEvent)); +}; +``` + +## Macrotasks ve Microtasks + +Bu bölümde açıklanan *macrotask*'ler ile birlikte, bölümünde bahsedilen *microtask*'ler vardır. + +Microtask'ler yalnızca kodumuzdan gelir. Genellikle promise'larla oluşturulurlar: `.then/catch/finally` işleyicisinin yürütülmesi bir microtask haline gelir. Microtask'ler, bir başka promise işleme biçimi olduğu için, `wait`'in "örtüsü altında" da kullanılır. + +Ayrıca, microtask kuyruğunda yürütülmek üzere `func`'u sıraya sokan özel bir `queueMicrotask(func)` fonksiyonu da vardır. + +**Her macrotask'dan hemen sonra, motor, diğer macrotask'ları çalıştırmadan veya oluşturmadan veya başka herhangi bir şeyden önce tüm görevleri microtask kuyruğundan yürütür.** + +Örneğin, bir göz atın: + +```js run +setTimeout(() => alert("timeout")); + +Promise.resolve() + .then(() => alert("promise")); + +alert("code"); +``` + +Buradaki sıra ne olacak? + +1. Sıradan bir eşzamanlı(synchronous) çağrı olduğu için önce `kod` gösterilir. +2. `promise` ikinci sıradadır, çünkü `.then` microtask kuyruğundan geçer ve geçerli koddan sonra çalışır. +3. `timeout`'u en son gösterir, çünkü bu bir macrotask'dir. + +Daha zengin olay döngüsü resmi şöyle görünür (sıra yukarıdan aşağıya doğrudur, yani: önce script, ardından microtask'ler, oluşturma(rendering) vb.): + +![](eventLoop-full.svg) + +Tüm microtask'ler, başka herhangi bir olay işleme(handling) veya oluşturma(rendering) veya başka herhangi bir macrotask gerçekleşmeden önce tamamlanır. + +Uygulama ortamının microtask'ler arasında temelde aynı olmasını (fare koordinat değişikliği yok, yeni ağ verisi yok, vb.) garanti ettiği için bu önemlidir. + +Bir fonksiyonu eşzamansız(asynchronously) olarak (geçerli koddan sonra) yürütmek istiyorsak, ancak değişiklikler oluşturulmadan(rendered) veya yeni olaylar işlenmeden(handled) önce, bunu `queueMicrotask` ile zamanlayabiliriz. + +Here's an example with "counting progress bar", similar to the one shown previously, but `queueMicrotask` is used instead of `setTimeout`. You can see that it renders at the very end. Just like the synchronous code: +Burada, daha önce gösterilene benzer bir "sayan ilerleme çubuğu" örneği verilmiştir, ancak `setTimeout` yerine `queueMicrotask` kullanılmıştır. En sonunda oluştuğunu(render) görebilirsiniz. Tıpkı senkron kod gibi: + +```html run +
+ + +``` + +## Özet + +Daha ayrıntılı bir olay döngüsü algoritması (yine de [spesifikasyona](https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model) kıyasla basitleştirilmiş olsa da): + +1. En eski görevi *macrotask* kuyruğundan ayırın ve çalıştırın (ör. "script"). +2. Tüm *microtask*'leri yürütün: + - Microtask kuyruğu boş değilken: + - En eski microtask'i sıraya alın ve çalıştırın. +3. Varsa oluşturme(render) değişiklikleri. +4. Macrotask kuyruğu boşsa, bir macrotask görünene kadar bekleyin. +5. 1.Adıma gidin. + +Yeni bir *macrotask* zamanlamak için: +- Sıfır gecikmeli `setTimeout(f)` kullanın. + +Bu, tarayıcının kullanıcı olaylarına tepki verebilmesi ve aralarındaki ilerlemeyi gösterebilmesi için büyük bir hesaplama ağırlıklı görevi parçalara ayırmak için kullanılabilir. + +Ayrıca, olay tamamen işlendikten (köpürme işlemi) sonra bir eylem zamanlamak için olay işleyicilerinde kullanılır. + +Yeni bir *microtask* planlamak için +- `queueMicrotask(f)` kullanın. +- Ayrıca promise işleyicileri microtask kuyruğundan geçer. + +Microtask'ler arasında UI veya ağ olayı işleme yoktur: Bunlar birbiri ardına hemen çalışır. + +Bu nedenle, bir fonksiyonu eşzamansız(asynchronously) olarak ancak ortam durumu içinde yürütmek için `queueMicrotask` isteyebilirsiniz. + +```smart header="Web Workers" +Olay döngüsünü engellememesi gereken uzun ağır hesaplamalar için [Web Workers](https://html.spec.whatwg.org/multipage/workers.html)'ı kullanabiliriz. + +Bu, başka bir paralel iş parçacığında(thread) kod çalıştırmanın bir yoludur. + +Web Workers ana süreçle mesaj alışverişinde bulunabilirler, ancak kendi değişkenleri ve kendi olay döngüleri vardır. + +Web Worker'larının DOM'a erişimi yoktur, bu nedenle, esas olarak hesaplamalar için, aynı anda birden fazla CPU çekirdeği kullanmak için yararlıdırlar. +``` diff --git a/2-ui/99-ui-misc/03-event-loop/eventLoop-full.svg b/2-ui/99-ui-misc/03-event-loop/eventLoop-full.svg new file mode 100644 index 000000000..201d9a14a --- /dev/null +++ b/2-ui/99-ui-misc/03-event-loop/eventLoop-full.svg @@ -0,0 +1 @@ +...mousemoveevent looprendermicrotasksrendermicrotasksscriptsetTimeout \ No newline at end of file diff --git a/2-ui/99-ui-misc/03-event-loop/eventLoop.svg b/2-ui/99-ui-misc/03-event-loop/eventLoop.svg new file mode 100644 index 000000000..f7de0b6ad --- /dev/null +++ b/2-ui/99-ui-misc/03-event-loop/eventLoop.svg @@ -0,0 +1 @@ +...mousemovescriptevent loopmacrotask queuesetTimeout \ No newline at end of file