node.js'nin console.log'u eşzamansız mı?


95

Are console.log/debug/warn/errornode.js asenkron içinde? Demek istediğim, javascript kodu yürütme işlemi ekranda yazdırılana kadar duracak mı yoksa daha sonraki bir aşamada yazdırılacak mı?

Ayrıca, bir console.log'un düğüm çökerttikten hemen sonra ifade herhangi bir şey GÖSTERMEMESİ mümkün olup olmadığını bilmekle ilgileniyorum.

Yanıtlar:


102

Güncelleme: Düğüm 0.6'dan başlayarak, stdout şu anda eşzamanlı olduğundan bu gönderi geçersizdir .

Peki console.logaslında ne yaptığını görelim .

Her şeyden önce konsol modülünün bir parçası :

exports.log = function() {
  process.stdout.write(format.apply(this, arguments) + '\n');
};

Bu yüzden sadece biraz biçimlendirme yapıyor ve yazıyor process.stdout, şimdiye kadar hiçbir şey eşzamansız değil.

process.stdoutBir alıcı olduğu başlangıçta tanımlanan lazily başlatılır, ben şeyleri açıklamaya bazı yorumlar ekledik:

.... code here...
process.__defineGetter__('stdout', function() {
  if (stdout) return stdout;                            // only initialize it once 

  /// many requires here ...

  if (binding.isatty(fd)) {                             // a terminal? great!
    stdout = new tty.WriteStream(fd);
  } else if (binding.isStdoutBlocking()) {              // a file?
    stdout = new fs.WriteStream(null, {fd: fd});
  } else {
    stdout = new net.Stream(fd);                        // a stream? 
                                                        // For example: node foo.js > out.txt
    stdout.readable = false;
  }

  return stdout;
});

Bir TTY ve UNIX durumunda, burada son buluruz , bu şey soketten miras alınır. Yani bu düğümün temelde yaptığı tek şey, veriyi sokete itmektir, ardından terminal gerisini halleder.

Hadi deneyelim!

var data = '111111111111111111111111111111111111111111111111111';
for(var i = 0, l = 12; i < l; i++) {
    data += data; // warning! gets very large, very quick
}

var start = Date.now();
console.log(data);
console.log('wrote %d bytes in %dms', data.length, Date.now() - start);

Sonuç

....a lot of ones....1111111111111111
wrote 208896 bytes in 17ms

real    0m0.969s
user    0m0.068s
sys  0m0.012s

Terminalin soket içeriğini yazdırması yaklaşık 1 saniyeye ihtiyaç duyar, ancak düğümün verileri terminale göndermek için yalnızca 17 milisaniyeye ihtiyacı vardır.

Aynı durum akış durumu için de geçerlidir ve dosya durumu da eşzamansız olarak ele alınır .

Yani evet, Node.js engellemeyen vaatlerine sadık kalıyor.


2
Güncelleme: node.js'deki stdout artık eşzamanlı: groups.google.com/group/nodejs/browse_thread/thread/…
dhruvbird

1
Bunun artık kullanılmadığını düşünüyorum: github.com/nodejs/node/issues/3524#issuecomment-151097761
tforgione

@IvoWetzel Eski olduğu için şimdi buna olumsuz oy vermem gerekecek.
Evan Carroll

Bunun eskimiş olduğunu ve her şeyin olduğunu biliyorum, ancak tanım gereği eşzamansız process.stdout.write()olduğu yerin hemen ardından "şimdiye kadar eşzamansız hiçbir şey" diyorsunuz write()
binki

27

console.warn () ve console.error () engelliyor. Temel sistem çağrıları başarılı olana kadar geri dönmezler.

Evet, standart çıktıya yazılan her şey temizlenmeden programdan çıkmak mümkündür. process.exit (), stdout'a sıraya alınmış yazmalar olsa bile düğümü hemen sonlandıracaktır. Bu davranıştan kaçınmak için console.warn kullanmalısınız.


1
Bu, Windows'taki Düğüm 0.10.25 için doğru değildir. console.warn()ve console.error()aynı engellemeyen davranışa sahiptir console.log(). Windows'ta sorunu çözmek için bir paket bile var .
Lucio Paiva

12

Sonuç, Node.js 10. * belgelerini okuduktan sonra (aşağıya eklenmiştir). günlük kaydı için console.log kullanabilmenizdir, console.log eşzamanlıdır ve düşük seviye c'de uygulanır. Console.log eşzamanlı olmasına rağmen, yalnızca büyük miktarda veri kaydetmiyorsanız bir performans sorununa neden olmaz.

(Komut satırı Aşağıdaki örnek console.log, göstermek uyumsuz ve console.error isimli senkronizasyon )

Dayanarak node.js Doc

Konsol işlevleri, hedef bir terminal veya dosya olduğunda senkronize (erken çıkış durumunda mesajların kaybolmasını önlemek için) ve bir boru olduğunda asenkron (uzun süre engellemekten kaçınmak için).

Yani, aşağıdaki örnekte, stderr bloke ederken stdout bloke edici değildir:

$ node script.js 2> error.log | tee info.log

Günlük kullanımda, büyük miktarlarda veri kaydetmediğiniz sürece engelleme / engellememe ikilemi endişelenmeniz gereken bir şey değildir.

Umarım yardımcı olur


"Büyük miktarda veri" nedir? Console.log'a yapılan çağrıların sayısı veya yazılan toplam miktar ile mi tanımlanıyor? Büyük 1KB / ms, 1MB / ms, 1GB / ms nedir?
MattG

3

Console.log, linux / mac'da eşzamanlıyken pencerelerde eşzamansızdır. Console.log'u pencerelerde eşzamanlı yapmak için bu satırı kodunuzun başlangıcına muhtemelen index.js dosyasına yazın. Bu ifadeden sonraki herhangi bir console.log, yorumlayıcı tarafından eşzamanlı olarak kabul edilecektir.

if (process.stdout._handle) process.stdout._handle.setBlocking(true);

Linux bu arada sadece ubuntu değil.
ozanmuyes

Sayenizde bilgiçlik yorumunu bahane ama Debian benim zayıf nokta olduğunu ve Linux kullanmaya başladı herkes bugünlerde Ubuntu düşünür görünüyor olduğunu (sen hariç ben onlardan biri olmadığını biliyoruz) Linux. İyi günler :)
ozanmuyes
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.