avatar
·4 dk okuma
Node.js'de Check Queue

Node.js'de Check Queue

Node.js, event-driven yapısı ve asenkron çalışma mantığı ile yüksek performanslı ve ölçeklenebilir uygulamalar geliştirmeye olanak tanır. Bu yapı içerisinde, event loop ve çeşitli callback kuyrukları (queues) büyük bir öneme sahiptir. Bu makalede, Node.js'deki check queue'yu ve diğer ilgili kuyrukları detaylı bir şekilde inceleyeceğiz. Ayrıca, çeşitli örneklerle bu kavramları pekiştireceğiz.

1. Event Loop ve Callback Kuyrukları

Node.js'deki event loop, ana iş parçacığını bloklamadan çeşitli asenkron işlemleri yönetir. Event loop'un farklı fazları vardır ve her faz belirli türdeki callback'leri işler:

  • Senkron Kod: İlk olarak çalıştırılan kod parçasıdır. Bu kod doğrudan çalıştırılır ve bloklama potansiyeline sahiptir.

  • Micro Task Queues: process.nextTick ve Promise.resolve gibi işlemlerle eklenen görevler bu kuyrukta yer alır. Mikro görevler, senkron koddan hemen sonra çalıştırılır ve yüksek önceliğe sahiptir.

  • Timer Queue: setTimeout ve setInterval gibi zamanlayıcılarla eklenen geri çağırma fonksiyonları bu kuyrukta toplanır. Belirtilen gecikme süresi tamamlandığında bu kuyruktaki görevler çalıştırılır.

  • I/O Queue: Dosya okuma/yazma, ağ işlemleri gibi I/O operasyonları tamamlandığında geri çağırma fonksiyonları bu kuyrukta yer alır ve zamanlayıcı kuyruğundan sonra çalıştırılır.

  • I/O Polling: I/O olaylarını işler ve yeni gelen I/O olaylarını bekler.

  • Check Kuyruğu: setImmediate callback'lerini işler.

  • Close Kuyruğu: Kapatma işlemleriyle ilgili callback'leri işler, örneğin socket.on('close', ...).

2. IO Polling ve Check Queue

IO polling ve check queue, Node.js'deki asenkron işlemleri anlamak için kritik öneme sahiptir. IO polling, dosya okuma/yazma gibi I/O işlemlerinin tamamlanmasını bekler. Bu işlemler tamamlandığında, ilgili callback'ler IO queue'ya eklenir. Check queue ise setImmediate tarafından eklenen callback'leri işler.

Önceki videolarımızda, IO polling'in IO queue ve check queue arasında nasıl gerçekleştiğini anladık. Örneğin, readFile işlemi sonrasında setImmediate'in kilitlenme sırasını inceledik. Şimdi bu konuyu daha derinlemesine inceleyelim.

3. Örnek 1: Callback Kuyruklarının Sıralaması

Bu örnekte, çeşitli callback kuyruklarının nasıl çalıştığını gözlemleyeceğiz.

Kod:

const fs = require('fs');

fs.readFile(__filename, (err, data) => {
    console.log('Read File Callback');
    setImmediate(()=> {
      console.log("ReadFile içinde Set Immediate Callback");
    })
});

process.nextTick(() => {
    console.log('Next Tick Callback');
});

Promise.resolve().then(() => {
    console.log('Promise Callback');
});

setTimeout(() => {
    console.log('Set Timeout Callback');
}, 0);

Bu kodda, readFile, setImmediate, process.nextTick, Promise.resolve ve setTimeout callback'lerinin çalışma sırasını inceleyeceğiz.

Beklenen Çıktı:

  • Next Tick Callback

  • Promise Callback

  • Set Timeout Callback

  • Read File Callback

  • ReadFile içinde Set Immediate Callback

Bu örnekten çıkarabileceğimiz önemli bir bilgi, micro task queue (process.nextTick ve Promise.resolve) callback'lerinin diğer tüm callback kuyruklarından önce çalıştığıdır.

check queue image

4. Örnek 2: readFile İçinde process.nextTick ve Promise.resolve

Bu örnekte, readFile callback'i içinde setImmediate'den sonra process.nextTick ve Promise.resolve ekleyeceğiz.

Kod:

const fs = require("fs");

fs.readFile(__filename, (err, data) => {
  console.log("Read File Callback");
  setImmediate(() => console.log("ReadFile içinde Set Immediate Callback"));
  process.nextTick(() => {
    console.log("ReadFile içinde Next Tick Callback");
  });

  Promise.resolve().then(() => {
    console.log("ReadFile içinde Promise Callback");
  });
});

process.nextTick(() => {
  console.log("Next Tick Callback");
});

Promise.resolve().then(() => {
  console.log("Promise Callback");
});

setTimeout(() => {
  console.log("Set Timeout Callback");
}, 0);

Bu değişiklikle, readFile callback'i içinde eklenen process.nextTick ve Promise.resolve callback'lerinin nasıl çalıştığını gözlemleyeceğiz.

Beklenen Çıktı:

  • Next Tick Callback

  • Promise Callback

  • Set Timeout Callback

  • Read File Callback

  • ReadFile içinde Next Tick Callback

  • ReadFile içinde Promise Callback

  • ReadFile içinde Set Immediate Callback

Bu örnekten çıkarabileceğimiz bilgi, readFile içinde eklenen micro task queue callback'lerinin, diğer micro task queue callback'lerinden sonra çalıştığıdır.

5. Örnek 3: Üç setImmediate Çağrısı ve process.nextTick ile Promise.resolve

Bu örnekte, üç setImmediate çağrısı yapacağız ve ikinci setImmediate içinde process.nextTick ve Promise.resolve ekleyeceğiz.

Kod:

setImmediate(() => console.log("Set Immediate Callback 1"));

setImmediate(() => {
  console.log("Set Immediate Callback 2");
  process.nextTick(() => {
    console.log("Set Immediate 2 içinde Next Tick Callback");
  });

  Promise.resolve().then(() => {
    console.log("Set Immediate 2 içinde Promise Callback");
  });
});

setImmediate(() => console.log("Set Immediate Callback 3"));

Bu kod ile, check queue callback'leri arasında micro task queue callback'lerinin çalıştığını gözlemleyeceğiz.

Beklenen Çıktı:

  • Set Immediate Callback 1

  • Set Immediate Callback 2

  • Set Immediate 2 içinde Next Tick Callback

  • Set Immediate 2 içinde Promise Callback

  • Set Immediate Callback 3

Bu örnek, micro task queue callback'lerinin check queue callback'lerinin arasında çalıştığını gösterir.

6. Örnek 4: setTimeout ve setImmediate Anomalisi

Bu örnekte, setTimeout (0ms gecikme ile) ve setImmediate çağrısı yapacağız.

Kod:

setTimeout(() => console.log("Set Timeout Callback 1"), 0);
setImmediate(() => console.log("Set Immediate Callback 1"));

Bu örnek, setTimeout ve setImmediate sırasının her zaman aynı olmadığını gösterir. IO queue ile ilgili önceki videoda açıklanan nedenlerden dolayı, bu işlemlerin sırası garanti edilemez.

Beklenen Çıktı: Çalıştırıldığında, çıktı değişebilir:

  • Set Timeout Callback 1

  • Set Immediate Callback 1 veya

  • Set Immediate Callback 1

  • Set Timeout Callback 1

Uzun süreli bir for döngüsü eklenirse, setTimeout her zaman setImmediate'den önce çalışır.

Sonuç

Bu makalede, Node.js'deki check queue ve ilgili diğer kuyrukların nasıl çalıştığını detaylı bir şekilde inceledik. Yapılan örnekler, bu kavramları anlamamıza yardımcı oldu ve Node.js'nin asenkron çalışma mantığını pekiştirdi. Check queue, event loop ve micro task queue gibi kavramlar, Node.js ile performanslı ve ölçeklenebilir uygulamalar geliştirmek için kritik öneme sahiptir.