Sanırım bunu gayet güzel bir şekilde açıklayabilirim. Yana nextTickyinelemeli çağırmak devam etmesini olay döngü engelleme sonunda olabilir, şimdiki operasyonun sonunda denir. setImmediatebunu 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, nextTickher işlemden sonra kontrol edilen ve teknik olarak olay döngüsünün dışında var olan hemen değil .
setImmediateVe 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 stepyineleme sıfır ile fonksiyonu. Daha sonra iki işleyicileri, diğeri kaydedecektir setImmediateve bir tane process.nextTick. Daha sonra bu işlevi bir setImmediatesonraki 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: nextTickgeç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 setImmediateyinelemeli olarak çağırır step. Geçerli işlem sona erer, nextTickyangı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 stepbizim nextTickiş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 stepiçine nextTickfarklı bir sırada davranacaktır işleyici şeyler. Olay döngüsünü ilk yinelememiz çalışır ve stepbir setImmedaiteişleyicinin yanı sıra bir nextTickişleyiciyi kaydetmeyi çağırır . Mevcut işlem sona erdikten sonra, başka bir işleyiciyi ve başka bir işleyiciyi nextTickyinelemeli olarak çağıran stepve 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ğizsetImmediatenextTicknextTicknextTicknextTicknextTicknextTicktek bir setImmediateiş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 nextTicketmeseydik , ç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 .setImmediatesetImmediate
Umarım yardımcı olur!
PS - Diğer yorumcularla, iki işlevin adlarının kolayca değiştirilebileceğine katılıyorum, çünkü nextTickgeç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.