DreamerBird Javascript single-threaded yani tek iş parçacıklı bir dil olduğu için tek seferde tek bir işlem yapabilir. O yüzden işler birbirini bloklar, biri bitmeden diğeri çalışmaz. Öte yandan yorumlanan bir dildir, yani derlenmez. Yorumlama işini ise Javascript motoru (engine) yapar. En çok bilinen ve kullanılan Javascript motoru ise Chrome V8'dir ama biz Javascript ile uğraşırken bu motor ile ilgili bir işlem yapmayız. Javascript motoru bir ortamda (environment) yer alır ve biz ortam ile haşır neşir oluruz. Bu ortamlar web API, kütüphane, tarayıcı vs olmuş oluyor. İşte bu noktada şöyle bir ayrım var, evet Javascript single-threaded bir dildir ama çalışma ortamı (runtime environment) öyle değildir. Çalışma ortamında iş parçacığı havuzu vardır ve işler havuza alınınca sync ya da aysnc programlama yapılabilir. Bunun sağlayan, hangi işin hangi sırada çalışacağını belirleyen ise çalışma ortamının sahip olduğu olay döngüsü mekanizmasıdır (event loop). Genel olarak Javascript'te kod iki şekilde çalışıyor; birincisi direkt, yani mesela console.log yazınca hemen çalışması gibi, diğeri ise callback şeklinde yani bir olaydan sonra ateşlenecek şekilde. Bu olay döngüsü mekanizması callback kısmını halleden mekanizma.
Şu işlemlere bakarsanız:
console.log("A")
setTimeout(()=>console.log("B"), 1)
console.log("C")
A
C
B
Javascript single-threaded dedik, bloklar dedik ama A B C şeklinde çıktı almamız gerekiyorken A C B şeklinde çıktı aldık. B işleminin C işlemini bloklaması gerekiyordu fakat olmadı. Bunun sebebi işte setTimeout işlemi burada, olay döngüsü mekanizması tarafından, çalışma ortamında gerçekleşen bir işlem oluyor. 3 işlem de sırayla çalışıyor aslında, birbirlerini blokladılar, ama setTimeout olay döngüsü mekanizması kuyruğuna bir iş parçacığı ekliyor, olay döngüsü mekanizması da sırası geldiğinde iş parçacığının çalışmasını sağlıyor. Sadece kendi içlerinde birbirlerini bloklayabilen iki iş parçacığı kuyruğu oluşmuş oluyor. Çalışma sırası doğru aslında, sizin istediğiniz sıra değil sadece çünkü siz bu durumda iki kuyruğun karışımından bir sıralama istiyorsunuz, bu mümkün mü? Evet ama 3. bir kuyruk ile.
const timer = new Promise((resolve, reject) => {
const i = setInterval(() => {
clearInterval(i);
resolve();
}, 3000);
});
timer.then(() => {
console.log('A');
})
3 saniye sonra A yazar fakat
timer.then(() => {
console.log('A');
})
console.log('B');
yaparsanız önce B yazar, sonra 3 saniye sonra A yazar. B yazan önce belleğe alınmadı ama, önce A işlemi alındı sonra B. Birbirlerini blokladılar, bloklanamayan ise olay döngüsü mekanizması kuyruğunda işlenen callback. O farklı bir kuyrukta işlendi çünkü. Aynı kuyruktaki iş parçacıkları birbirini bloklayabilir.
function sleep() {
return new Promise((resolve, reject) => {
const i = setInterval(() => {
clearInterval(i);
resolve();
}, 3000);
});
}
function loggingThread(content) {
console.log(content)
}
// Burası sizin sıralı iş parçacığı kuyruğunuz yani 3. kuyruk:
async function threadQueue() {
loggingThread('A'); // 1. iş parçacığı
await sleep();
loggingThread('B'); // 2. iş parçacığı
await sleep();
loggingThread('C'); // 3. iş parçacığı
}
threadQueue();
A
B
C
şeklinde yapmanız gerekiyor.
Bu durumda "Nerede yanlış yapıyorum ?" sorunuzun cevabı iş parçacığı kuyruklarını karıştırıyorsunuz olmuş oluyor. Blocking, seri bir yapı için yapmanız gereken kendi iş parçacığı kuyruğunuzu oluşturmak, üstteki async function threadQueue() gibi. Böylece akışı kontrol altında tutabilirsiniz.
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide/In_depth
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals