Sanırım bunu gayet güzel bir şekilde açıklayabilirim. Yana nextTick
yinelemeli çağırmak devam etmesini olay döngü engelleme sonunda olabilir, şimdiki operasyonun sonunda denir. setImmediate
bunu olay döngüsünün kontrol aşamasında ateşleyerek olay döngüsünün normal şekilde devam etmesini sağlayarak çözer.
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
kaynak: https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
Kontrol aşamasının anket aşamasından hemen sonra olduğuna dikkat edin. Bunun nedeni, anket aşaması ve G / Ç geri çağrılarının, aramalarınızın gerçekleştirileceği en olası yerler olmasıdır setImmediate
. İdeal olarak, bu çağrıların çoğu aslında hemen gerçekleşecek, nextTick
her işlemden sonra kontrol edilen ve teknik olarak olay döngüsünün dışında var olan hemen değil .
setImmediate
Ve arasındaki farkın küçük bir örneğine bakalım process.nextTick
:
function step(iteration) {
if (iteration === 10) return;
setImmediate(() => {
console.log(`setImmediate iteration: ${iteration}`);
step(iteration + 1); // Recursive call from setImmediate handler.
});
process.nextTick(() => {
console.log(`nextTick iteration: ${iteration}`);
});
}
step(0);
Diyelim ki bu programı yeni çalıştırdık ve olay döngüsünün ilk yinelemesinden geçiyoruz. İçine arayacak step
yineleme sıfır ile fonksiyonu. Daha sonra iki işleyicileri, diğeri kaydedecektir setImmediate
ve bir tane process.nextTick
. Daha sonra bu işlevi bir setImmediate
sonraki kontrol aşamasında çalışacak olan işleyiciden özyineli olarak çağırırız . nextTick
İşleyicisi ikinci kaydedildi aslında ilk çalışacağı, böylece bile olsa olay döngü kesintiye Mevcut işlemin sonunda çalışacaktır.
Sıra şu şekilde biter: nextTick
geçerli işlem sona erdiğinde tetiklenir, bir sonraki olay döngüsü başlar, normal olay döngü aşamaları yürütülür, tetiklenir ve işlemi tekrar tekrar başlatmak için işlevimizi setImmediate
yinelemeli olarak çağırır step
. Geçerli işlem sona erer, nextTick
yangınlar vb.
Yukarıdaki kodun çıktısı:
nextTick iteration: 0
setImmediate iteration: 0
nextTick iteration: 1
setImmediate iteration: 1
nextTick iteration: 2
setImmediate iteration: 2
nextTick iteration: 3
setImmediate iteration: 3
nextTick iteration: 4
setImmediate iteration: 4
nextTick iteration: 5
setImmediate iteration: 5
nextTick iteration: 6
setImmediate iteration: 6
nextTick iteration: 7
setImmediate iteration: 7
nextTick iteration: 8
setImmediate iteration: 8
nextTick iteration: 9
setImmediate iteration: 9
Şimdi özyinelemeli çağrımızı yerine step
bizim nextTick
işleyicimize taşıyalım setImmediate
.
function step(iteration) {
if (iteration === 10) return;
setImmediate(() => {
console.log(`setImmediate iteration: ${iteration}`);
});
process.nextTick(() => {
console.log(`nextTick iteration: ${iteration}`);
step(iteration + 1); // Recursive call from nextTick handler.
});
}
step(0);
Şimdi biz özyinelemeli çağrı taşımış olduğu step
içine nextTick
farklı bir sırada davranacaktır işleyici şeyler. Olay döngüsünü ilk yinelememiz çalışır ve step
bir setImmedaite
işleyicinin yanı sıra bir nextTick
işleyiciyi kaydetmeyi çağırır . Mevcut işlem sona erdikten sonra, başka bir işleyiciyi ve başka bir işleyiciyi nextTick
yinelemeli olarak çağıran step
ve kaydeden işleyici yangınlarımız . Bir işleyici geçerli işlemden sonra ateş ettiğinden, bir işleyicinin bir işleyiciye kaydedilmesi , ikinci işleyicinin geçerli işleyici işlemi tamamlandıktan hemen sonra çalışmasına neden olur. İşleyicileri hiç devam etmesini güncel olay döngü önlenmesi, ateş tutacak. Tüm bunlardan geçeceğizsetImmediate
nextTick
nextTick
nextTick
nextTick
nextTick
nextTick
tek bir setImmediate
işleyici yangını görmeden önce işleyicileri.
Yukarıdaki kodun çıktısı şu şekildedir:
nextTick iteration: 0
nextTick iteration: 1
nextTick iteration: 2
nextTick iteration: 3
nextTick iteration: 4
nextTick iteration: 5
nextTick iteration: 6
nextTick iteration: 7
nextTick iteration: 8
nextTick iteration: 9
setImmediate iteration: 0
setImmediate iteration: 1
setImmediate iteration: 2
setImmediate iteration: 3
setImmediate iteration: 4
setImmediate iteration: 5
setImmediate iteration: 6
setImmediate iteration: 7
setImmediate iteration: 8
setImmediate iteration: 9
Özyinelemeli çağrıyı yarıda kesip 10 yinelemeden sonra iptal nextTick
etmeseydik , çağrılar tekrarlamaya devam eder ve olay döngüsünün bir sonraki aşamaya devam etmesine asla izin vermez. Bir sonraki olay döngüsünde ateşlenecek ve bir başka işleyiciyi birinden ayarlamak geçerli olay döngüsünü hiç kesmeyecek ve böylece olay döngüsünün aşamalarını normal şekilde yürütmeye devam etmesine izin verecek şekilde, nextTick
özyinelemeli olarak kullanıldığında nasıl engellenebilir .setImmediate
setImmediate
Umarım yardımcı olur!
PS - Diğer yorumcularla, iki işlevin adlarının kolayca değiştirilebileceğine katılıyorum, çünkü nextTick
geçerli olanın sonu yerine bir sonraki olay döngüsünde patlayacak gibi geliyor ve geçerli döngünün sonu daha "hemen" "bir sonraki döngünün başlangıcından daha fazla. Ah, API olgunlaştıkça bunu elde ederiz ve insanlar mevcut arayüzlere bağımlı hale gelirler.