NodeJS - setTimeout (fn, 0) ile setImmediate (fn) karşılaştırması


Yanıtlar:


72

setTimeout , gecikme bittikten sonra işlevi çağırmak gibidir. Bir işlev çağrıldığında, hemen çalıştırılmaz, ancak sıraya alınır, böylece tüm çalıştırma işlemlerinden sonra yürütülür ve şu anda sıraya alınmış olan çiftler birinci bitirir. setTimeout (, 0) esasen mevcut kuyruktaki tüm geçerli işlevler yürütüldükten sonra çalıştırılması anlamına gelir. Ne kadar süreceği konusunda hiçbir garanti verilemez.

setImmediate , işlev kuyruğunu kullanmaması dışında bu açıdan benzerdir. G / Ç çift taşıyıcılarının sırasını kontrol eder. Geçerli anlık görüntüdeki tüm G / Ç olayları işlenirse, geri aramayı yürütür. İşlem.nextTick gibi, son G / Ç işleyicisinden hemen sonra onları sıraya koyar. Yani daha hızlı.

Ayrıca (setTimeout, 0) yavaş olacaktır çünkü yürütmeden önce zamanlayıcıyı en az bir kez kontrol edecektir. Bazen iki kat daha yavaş olabilir. İşte bir kriter.

var Suite = require('benchmark').Suite
var fs = require('fs')

var suite = new Suite

suite.add('deffered.resolve()', function(deferred) {
  deferred.resolve()
}, {defer: true})

suite.add('setImmediate()', function(deferred) {
  setImmediate(function() {
    deferred.resolve()
  })
}, {defer: true})

suite.add('setTimeout(,0)', function(deferred) {
  setTimeout(function() {
    deferred.resolve()
  },0)
}, {defer: true})

suite
.on('cycle', function(event) {
  console.log(String(event.target));
})
.on('complete', function() {
  console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
.run({async: true})

Çıktı

deffered.resolve() x 993 ops/sec ±0.67% (22 runs sampled)
setImmediate() x 914 ops/sec ±2.48% (57 runs sampled)
setTimeout(,0) x 445 ops/sec ±2.79% (82 runs sampled)

İlki, mümkün olan en hızlı aramalar hakkında fikir verir. SetTimeout'un diğerlerinin yarısı kadar çağrılıp çağrılmadığını kendiniz kontrol edebilirsiniz. Ayrıca setImmediate'in dosya sistemi çağrılarınıza uyum sağlayacağını unutmayın. Yani yük altında daha az performans gösterecektir. SetTimeout'un daha iyisini yapabileceğini sanmıyorum.

setTimeout, bir süre sonra işlevleri çağırmanın müdahaleci olmayan bir yoludur. Tıpkı tarayıcıdaki gibi. Sunucu tarafı için uygun olmayabilir (neden setTimeout değil benchmark.js kullandığımı düşünün).


3
SetTimeout'un, beş kez iç içe yerleştirilmesi durumunda en az dört milisaniyelik bir zorunlu gecikmeye tabi olduğuna dikkat etmek önemlidir. html özelliklerine bakın
Jack Allan

Bu kaynak (diğer yanıttan) buradaki bazı ifadeleri çürütüyor gibi görünüyor: voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout
Dmitri Zaitsev

17

Olay döngüsünün nasıl çalıştığı ve bazı yanlış anlamaları ortadan kaldırdığı hakkında harika bir makale. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/

Makaleden alıntı yapmak:

setImmediategeri aramalar, G / Ç Sırası geri aramaları tamamlandıktan veya zaman aşımına uğradıktan sonra çağrılır. setImmediate geri aramaları, G / Ç Sırasından sonra işlenen Kontrol Sırasına yerleştirilir.

setTimeout(fn, 0)geri aramalar Zamanlayıcı Kuyruğuna yerleştirilir ve G / Ç geri aramalarının yanı sıra Check Queue geri aramalarından sonra çağrılır. Olay döngüsü olarak, her yinelemede ilk olarak zamanlayıcı kuyruğunu işleyin, böylece hangisinin ilk olarak yürütüleceği, hangi faz olay döngüsünün olduğuna bağlıdır.


setTimeout kuyruğu, G / Ç geri aramalarından önce işlenir. ref: nodejs.org/en/docs/guides/event-loop-timers-and-nexttick
insan

4

setImmediate () , G / Ç olayları geri aramalarından sonra ve setTimeout ve setInterval'dan önce geri aramanın hemen yürütülmesini planlamaktır.

setTimeout () , milisaniye gecikmesinden sonra bir kerelik geri aramanın yürütülmesini planlamaktır.

Belgelerin söylediği bu.

setTimeout(function() {
  console.log('setTimeout')
}, 0)

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

Yukarıdaki kodu çalıştırırsanız, sonuç şu şekilde olacaktır ... mevcut belgede "G / Ç olayları geri aramalarından sonra ve setTimeout ve setInterval'dan önce geri aramanın" anında "yürütülmesini planlamak için." ..

Sonuç..

setTimeout

setImmediate

Örneğinizi başka bir zamanlayıcıya sararsanız, her zaman setImmediate ve ardından setTimeout yazdırır.

setTimeout(function() {
  setTimeout(function() {
    console.log('setTimeout')
  }, 0);
  setImmediate(function() {
    console.log('setImmediate')
  });
}, 10);

Peki birini diğerine ne zaman tercih edeceksiniz?
Shlomi Schwartz

23
Gösterdiklerinin neden olduğunu açıklamadın. Bu cevap benim için yararlı değildi.
Clint Eastwood

3
@Savannah İlk sonucunuzda, lütfen setTimeout'un neden setImmediate'ten önce ilk olarak uygulandığını açıklayın
Agus Syahputra


1
SetImmediate, setTimeout'tan önce çalıştırılmayacak ve her zaman setInterval
Midhun GS

2

setImmediateİhtiyaç duyduğunuzdan gerçekten emin değilseniz her zaman kullanın setTimeout(,0)(ama ne için olduğunu hayal bile edemiyorum). setImmediategeri arama, setTimeout(,0)ilk tikte ve setImmediategeri aramada çağrılmadıkça hemen hemen her zaman daha önce yürütülür .


1
SetImmediate yerine setTimeout kullanmanın ana nedeninin, kodunuzun setImmediate uygulanmamış tarayıcılar tarafından yürütülmesi gerektiğini söyleyebilirim. O zaman bile, sadece bir şim oluşturabilirsiniz.
Gregory Magarshak

9
Bu mantıksız bir tavsiye. Her şey önce gitmeyi isterse, eşzamansız yürütmenin ortaya çıkan performans özellikleri, sondaki kuyruğa göre önemsiz olacaktır. setTimeoutile, go-olmalıdır setImmediategerekli olduğu gösterilmiştir yalnızca kullandı.
Rich Remer

1

Verilen cevaplardan tamamen memnun kalmadım. Burada daha iyi bir cevap olduğunu düşündüğüm şeyi yayınladım: https://stackoverflow.com/a/56724489/5992714

Sorular, ana modülde kullanıldığında setTimeout (0) ve setImmediate () davranışları neden tanımsızdır?


1
Lütfen iki soruya tam olarak aynı cevabı göndermeyin. Sorular farklıysa, yanıtı her birine uygun hale getirin. Aynıysa, birini kopya olarak kapatmak için işaretleyin veya oylayın.
Tom Zych

@TomZych kaydetti.
insan

0

Navya S'nin cevabının doğru olmadığını düşünüyorum , işte test kodum:

let set = new Set();

function orderTest() {
  let seq = [];
  let add = () => set.add(seq.join());
  setTimeout(function () {
    setTimeout(function () {
      seq.push('setTimeout');
      if (seq.length === 2) add();
    }, 0);

    setImmediate(function () {
      seq.push('setImmediate');
      if (seq.length === 2) add();
    });
  }, 10);
}

// loop 100 times
for (let i = 0; i < 100; i++) {
  orderTest();
}

setTimeout(() => {
  // will print one or two items, it's random
  for (item of set) {
    console.log(item);
  }
}, 100);

Açıklamalar burada


0

setTimeout (fn, 0), tarayıcının büyük güncellemelerde donmasını önlemek için kullanılabilir. örneğin websocket.onmessage'da html değişiklikleriniz olabilir ve mesajlar gelmeye devam ederse setImmidiate kullanırken tarayıcı donabilir


0

Bunları derinlemesine anlamak için lütfen bir kez olay döngüsü aşamalarından geçin.

SetImmediate: "kontrol" aşamasında çalıştırılır. Onay faz I / O aşamasından sonra adlandırılır.

SetTimeOut: "timer" aşamasında çalıştırılır. Zamanlayıcı faz ilk aşamasıdır ama sonra çağrılan G / Ç fazı yanı sıra kontrol fazı.

Çıktıyı belirleyici bir şekilde elde etmek için, olay döngüsünün hangi fazda olduğuna bağlı olacaktır; buna göre, işlevi ikiden kullanabiliriz.


-5

olay döngüsünü engellememek için setImmediate () kullanın. Geri arama, mevcut olay tamamlanır tamamlanmaz bir sonraki olay döngüsünde çalışacaktır.

kontrollü gecikmeler için setTimeout () kullanın. Fonksiyon, belirtilen gecikmeden sonra çalışacaktır. Minimum gecikme 1 milisaniyedir.

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.