nextTick vs setImmediate, görsel açıklama


91

NextTick ve setImmediate arasındaki farklar konusunda kafam çok karışık. Onlarla ilgili tüm belgeleri internette okudum ama nasıl çalıştıklarını hala anlamıyorum.

Örnekler:

function log(n) { console.log(n); }

setImmediate

setImmediate(function() {
  setImmediate(function() {
    log(1);
    setImmediate(function() { log(2); });
    setImmediate(function() { log(3); });
  });
  setImmediate(function() {
    log(4);
    setImmediate(function() { log(5); });
    setImmediate(function() { log(6); });
  });
});

//1 2 3 4 5 6

nextTick

process.nextTick(function() {
  process.nextTick(function() {
    log(1);
    process.nextTick(function() { log(2); });
    process.nextTick(function() { log(3); });
  });
  process.nextTick(function() {
    log(4);
    process.nextTick(function() { log(5); });
    process.nextTick(function() { log(6); });
  });
});

//1 4 2 3 5 6

Neden bu sonuçlar? Lütfen görsel veya takip etmesi çok kolay bir açıklama ile açıklayınız. Düğüm çekirdeği geliştiricileri bile nextTick ve setImmediate'in insanlar tarafından nasıl anlaşılması gerektiği konusunda hemfikir değil.

Kaynaklar:


8
Harika soru. Bu, farklılıkları göstermenin mükemmel bir yoludur.
SystemParadox

8
Çıktı 1 4 2 3 5 6her iki yürütme için de aynı ( ) (Node v5.6.0)
Deniz Özger

Bilge ve yardımcı soru!
Mehdi Raash

her ikisi de aynı çıktıyı üretir
MechaCode

1
5 yıl önceki yıla bakın! Pek çok şey değişebilirdi.
Gabriel Llamas

Yanıtlar:


105

Aşağıdaki iki örneği düşünün:

setImmediate

setImmediate(function A() {
  setImmediate(function B() {
    log(1);
    setImmediate(function D() { log(2); });
    setImmediate(function E() { log(3); });
  });
  setImmediate(function C() {
    log(4);
    setImmediate(function F() { log(5); });
    setImmediate(function G() { log(6); });
  });
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0)

// 'TIMEOUT FIRED' 1 4 2 3 5 6
// OR
// 1 'TIMEOUT FIRED' 4 2 3 5 6

nextTick

process.nextTick(function A() {
  process.nextTick(function B() {
    log(1);
    process.nextTick(function D() { log(2); });
    process.nextTick(function E() { log(3); });
  });
  process.nextTick(function C() {
    log(4);
    process.nextTick(function F() { log(5); });
    process.nextTick(function G() { log(6); });
  });
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0)

// 1 4 2 3 5 6 'TIMEOUT FIRED'

setImmediate geri aramaları, sıraya konuldukları sırayla her yineleme için bir kez olay döngüsünden çıkar. Dolayısıyla, olay döngüsünün ilk yinelemesinde geri çağırma A tetiklenir. Daha sonra olay döngüsünün ikinci yinelemesinde geri arama B çalıştırılır, ardından olay döngüsü geri aramasının üçüncü yinelemesinde C tetiklenir, vb. Bu, olay döngüsünün engellenmesini önler ve diğer G / Ç veya zamanlayıcı geri aramalarının yapılmasına izin verir. ortalama sürede çağrılır (1. veya 2. döngü yinelemesinde tetiklenen 0ms zaman aşımı durumunda olduğu gibi).

Ancak nextTick geri aramaları her zaman geçerli kodun yürütülmesi tamamlandıktan hemen sonra ve olay döngüsüne geri dönmeden ÖNCE tetiklenir. NextTick örneğinde, olay döngüsüne geri dönmeden önce tüm nextTick geri aramalarını yürütmeyi sonlandırıyoruz. SetTimeout'un geri araması olay döngüsünden çağrılacağından, her nextTick geri aramasını bitirene kadar 'TIMEOUT FIRED' metni çıktılanmayacaktır.


8
Mükemmel, son paragraf ana farkı anlamanın anahtarıdır.
Gabriel Llamas

nextTick örneğinizin farklı çıktıları var:TIMEOUT FIRED 1 4 2 3 5 6
Jürgen Paul

Hangi düğüm sürümünü çalıştırıyorsunuz? 0.10.x düğümünde her zaman nextTick geri aramalarınızı olay döngüsüne ulaşmadan önce çalıştırmalısınız.
Dave Stibrany

23
Keşke farklı bir isim seçselerdi. Şu anda "nextTick", setImmediate'den daha hızlı.
skerit

1
@StrugglingCoder Çünkü A yürütüldüğünde, B ve C'yi bir sonraki programlanacak şekilde ayarlar. B yürütüldüğünde, D ve E'yi bir sonraki programlanacak şekilde ayarlar, ancak C zaten B'den sonra planlanmıştır. Geri aramanın ne zaman planlandığı veya kaydedildiği ile geri aramanın fiilen tetiklendiği zaman arasında bir fark olduğunu unutmayın.
Dave Stibrany

25

Node.js'ye göre bu iki işlevin doc adları tam olarak değiştirilir

setImmediate () ( EN İYİ TAVSİYE )

Olay kuyruğunda önce ateşleniyor


process.nextTick () ( ÖZEL DURUMLAR İÇİN KULLANIN, daha sonra örneğe bakın )

Hemen yanıyor, şu anki dosyanın sonuna daha çok bir ifade yazıyor


Bu koda sahipsek

setTimeout(function(){
  console.log('Hello world 5'); // It's waiting like a normal person at a queue
}, 0);

setImmediate(function(){
  console.log('Hello world 4'); 
  // It's like get to last and be take care of first 
  // but always after of .nextTick and before of setInterval(, 0)
});

process.nextTick(function(){
   console.log('Hello world 3'); // It's like be at the bottom at this file
});

console.log('Hello world 1');
console.log('Hello world 2');

İsteğinize göre görsel bir açıklama:

görüntü açıklamasını buraya girin

Process.nextTick () 'i kullanmadan önce yaymanız ve olay yapmanız gerektiğinde kullanım durumları:

const EventEmitter = require('events');
const util = require('util');

function MyEmitter() {
  EventEmitter.call(this);

  // use nextTick to emit the event once a handler is assigned
  process.nextTick(function () {
    this.emit('event');
  }.bind(this));
}
util.inherits(MyEmitter, EventEmitter);

const myEmitter = new MyEmitter();
myEmitter.on('event', function() {
  console.log('an event occurred!');
});

Nerede bu vide bak Philip Roberts ayıklayıcı bu online eventloop bize çalışma zamanı olay döngü ve görünüm hakkında çok açıklama Canlı testi nasıl olay döngü çalışmaları

Kaynak: https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vs-setimmediate


1
Bu cevap daha mantıklı! Teşekkürler @gsalgadotoledo: p adamım, nextTick ve setImmediate'i anlamaktan daha adınızı yazmak daha zordu.
Aimal Khan

8

İçin sonuçlarını çoğaltamıyorum setImmediate. Bu, nextTick(ve benim testlerimde) ile aynı olmalıdır çünkü bu durumda hemen hemen aynı şeyi yaparlar. Bunun için tek makul açıklama, bunun setImmediatebir şekilde eşzamanlı olduğu, ama değil.

Ve NodeJS belgelerine göre tek gerçek fark, nextTickbir döngü yinelemesinde (bağlı olarak maxTickDepth) çoklu , yinelemede bir setImmediatekez ateşlenebilmesidir.


4

Aşağıda size daha iyi bir netlik sağlar.

setImmediate

  1. Mevcut anket aşaması tamamlandığında bir komut dosyası çalıştırır.
  2. Bu bir zamanlayıcı modülü işlevidir ve zamanlayıcı işlevleri globaldir, bunları olmadan da çağırabilirsiniz require.
  3. ClearImmediate () ile temizlenebilir.
  4. SetTimeout () ve setInterval () öncesinde G / Ç olaylarının geri aramalarından sonra geri aramanın "anında" yürütülmesini ayarlayın.

nextTick

  1. Bu, NodeJS'nin bir süreç genel nesne işlevidir.
  2. Process.nextTick () öğesine iletilen tüm geri çağrılar, olay döngüsü devam etmeden önce çözümlenecektir.
  3. Kullanıcıların hataları işlemesine izin verin.
  4. Olay döngüsü devam etmeden önce isteğin tekrar denenmesine yardımcı olur.

Basit kod Snippet'i.

console.log("I'm First");

setImmediate(function () {
  console.log('Im setImmediate');
});

console.log("I'm Second");

process.nextTick(function () {
  console.log('Im nextTick');
});

console.log("I'm Last");

/*
Output
$ node server.js
I'm First
I'm Second
I'm Last
Im nextTick
Im setImmediate
*/

2

Sanırım yukarıdaki yanıtların tümü geçerliliğini yitirmiş, çünkü nodejs'nin güncel sürümüyle sürekli olarak farklı yanıtlar aldım ve bunun hakkında akıl yürütmek kolay

var log=console.log
log(process.version)

var makeAsyncCall
if(false)
    makeAsyncCall=setImmediate
else
    makeAsyncCall=process.nextTick;

makeAsyncCall(function A () {
    makeAsyncCall(function B() {
        log(1);
        makeAsyncCall(function C() { log(2); });
        makeAsyncCall(function D() { log(3); });
    });
    makeAsyncCall(function E() {
        log(4);
        makeAsyncCall(function F() { log(5); });
        makeAsyncCall(function G() { log(6); });
    });
});
//1
//4
//2
//3
//5
//6
//in both case

Https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vs-setimmediate'i okuduktan sonra kullanmaya başlayalım, setImmediatetakip etmeliyiz check queuenerede o çünkü setImmediategeri arama huzurunuzda.

İlk yineleme

A itiliyor check queue

kuyruğu kontrol et: [A]

İkinci yineleme

Aqueueyürütmek için çekilir

Yürütme sırasında, koyun Bve Eiçin queue, sonra ve Atam ve sonraki iterasyon başlatmak

kuyruğu kontrol et: [B, E]

Üçüncü yineleme

çek Bve itC D

kuyruğu kontrol edin: [E, C, D]

Dördüncü yineleme

çek Eve itF G

kuyruğu kontrol edin: [C, D, F, G]

En sonunda

Kuyruktaki geri aramaları sırayla yürütür

İçin nextTickdurumunda, kuyruk tamamen aynı şekilde çalışır, aynı sonucu üretmek neden olmasıdır

Farklı olan şudur:

nextTickQueue, olay döngüsünün mevcut aşamasına bakılmaksızın, geçerli işlem tamamlandıktan sonra işlenecektir.

Açık olmak gerekirse, olay döngüsü birden fazla kuyruğu korur ve check queuebunlardan yalnızca biridir, düğüm bazı kurallara göre hangi kuyruğun kullanılacağına karar verir.

ile process.nextTickancak, sıralama tüm kuralı atlayarak sahiptir ve içinde geri arama yürütmek nextTickhemen

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.