czy plik console.log node.js jest asynchroniczny?


95

Czy console.log/debug/warn/errorplik node.js jest asynchroniczny? Mam na myśli, czy wykonywanie kodu javascript zatrzyma się do momentu wydrukowania treści na ekranie, czy też zostanie wydrukowane w późniejszym etapie?

Chciałbym też wiedzieć, czy jest możliwe, aby plik console.log NIE wyświetlał niczego, jeśli instrukcja natychmiast po awarii węzła.

Odpowiedzi:


102

Aktualizacja: Począwszy od Node 0.6 ten post jest przestarzały, ponieważ stdout jest teraz synchroniczny .

Zobaczmy, co console.logtak naprawdę robi.

Przede wszystkim jest częścią modułu konsoli :

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

Więc po prostu wykonuje pewne formatowanie i zapisuje process.stdout, jak na razie nic asynchronicznego.

process.stdoutto getter zdefiniowany podczas uruchamiania, który jest inicjowany leniwie, dodałem kilka komentarzy, aby wyjaśnić:

.... 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;
});

W przypadku TTY i UNIXa kończymy tutaj , ta rzecz dziedziczy z gniazda. Więc wszystko, co w zasadzie robi ten węzeł, to wypychanie danych do gniazda, a następnie terminal zajmuje się resztą.

Przetestujmy to!

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);

Wynik

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

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

Terminal potrzebuje około 1 sekundy na wydrukowanie zawartości gniazd, ale węzeł potrzebuje tylko 17 milisekund na przesłanie danych do terminala.

To samo dotyczy przypadku strumienia, a także przypadek pliku jest obsługiwany asynchronicznie .

Więc tak, Node.js spełnia swoje nieblokujące obietnice.


2
Aktualizacja: stdout w node.js jest teraz synchroniczny: groups.google.com/group/nodejs/browse_thread/thread/…
dhruvbird

1
Myślę, że to jest teraz przestarzałe: github.com/nodejs/node/issues/3524#issuecomment-151097761
tforgione

@IvoWetzel Będę musiał to teraz odrzucić, ponieważ jest przestarzałe.
Evan Carroll,

Wiem, że to jest przestarzałe i wszystko, ale mówisz „jak dotąd nic asynchronicznego” zaraz po tym, process.stdout.write()gdzie write()jest z definicji asynchroniczne…
binki

27

console.warn () i console.error () są blokujące. Nie wracają, dopóki nie powiodą się podstawowe wywołania systemowe.

Tak, możliwe jest, że program zakończy działanie, zanim wszystko, co zostało zapisane na stdout, zostanie opróżnione. process.exit () natychmiast zakończy działanie node, nawet jeśli nadal istnieją zapisy w kolejce na standardowe wyjście. Aby uniknąć tego zachowania, należy użyć console.warn.


1
Nie dotyczy to węzła 0.10.25 w systemie Windows. console.warn()i console.error()mają takie samo nieblokujące zachowanie jak console.log(). Jest nawet pakiet do rozwiązania problemu w systemie Windows .
Lucio Paiva,

12

Moje wnioski, po przeczytaniu dokumentów Node.js 10. * (załączone poniżej). polega na tym, że możesz użyć console.log do logowania, console.log jest synchroniczna i zaimplementowana na niskim poziomie c. Chociaż console.log jest synchroniczna, nie spowoduje problemów z wydajnością tylko wtedy, gdy nie rejestrujesz dużej ilości danych.

(Poniższy przykład wiersza poleceń demonstruje, console.log async i console.error to synchronizacja )

Na podstawie Node.js Doc's

Funkcje konsoli są synchroniczne, gdy miejscem docelowym jest terminal lub plik (aby uniknąć utraty wiadomości w przypadku przedwczesnego wyjścia) i asynchroniczne, gdy jest to potok (aby uniknąć blokowania przez długi czas).

Oznacza to, że w poniższym przykładzie stdout nie blokuje, podczas gdy stderr jest blokowane:

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

W codziennym użytkowaniu dychotomia blokująca / nieblokująca nie jest czymś, czym powinieneś się martwić, chyba że rejestrujesz duże ilości danych.

Mam nadzieję, że to pomoże


Co to jest „ogromna ilość danych”? Czy jest to określone przez liczbę wywołań do console.log czy całkowitą zapisywaną kwotę? Co to jest ogromny 1KB / ms, 1 MB / ms, 1 GB / ms?
MattG,

3

Console.log jest asynchroniczny w systemie Windows, podczas gdy jest synchroniczny w linux / mac. Aby uczynić console.log synchronicznym w systemie Windows, napisz tę linię na początku kodu, prawdopodobnie w pliku index.js. Każdy plik console.log po tej instrukcji będzie traktowany jako synchroniczny przez interpreter.

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

Nawiasem mówiąc, Linux to nie tylko ubuntu.
ozanmuyes

Dzięki, przepraszam za mój pedantyczny komentarz, ale Debian jest moim słabym punktem i wydaje się, że każdy, kto zaczął używać Linuksa w dzisiejszych czasach, myśli, że Ubuntu to Linux (z wyjątkiem ciebie, wiem, że nie jesteś jednym z nich). Miłego dnia :)
ozanmuyes
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.