Ist die console.log von node.js asynchron?

95

Sind console.log/debug/warn/errorin node.js asynchrone? Ich meine, wird die Ausführung von Javascript-Code angehalten, bis das Material auf dem Bildschirm gedruckt wird, oder wird es zu einem späteren Zeitpunkt gedruckt?

Außerdem interessiert mich, ob es möglich ist, dass in einem console.log nichts angezeigt wird, wenn die Anweisung unmittelbar nach dem Absturz des Knotens angezeigt wird.

Dhruvbird
quelle

Antworten:

101

Update: Ab Knoten 0.6 ist dieser Beitrag veraltet, da stdout jetzt synchron ist .

Mal sehen, was console.logeigentlich macht.

Zuallererst ist es Teil des Konsolenmoduls :

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

Es werden also einfach einige Formatierungen und Schreibvorgänge durchgeführt process.stdout, bisher nichts Asynchrones.

process.stdoutist ein beim Start definierter Getter , der träge initialisiert wird. Ich habe einige Kommentare hinzugefügt, um die Dinge zu erklären:

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

Im Falle eines TTY und UNIX landen wir hier , dieses Ding erbt von Socket. Alles, was dieser Knoten grundsätzlich tut, ist, die Daten auf den Socket zu übertragen, und das Terminal kümmert sich um den Rest.

Lass es uns testen!

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

Ergebnis

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

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

Das Terminal benötigt ungefähr 1 Sekunde, um den Socket-Inhalt auszudrucken, aber der Knoten benötigt nur 17 Millisekunden, um die Daten zum Terminal zu übertragen.

Gleiches gilt für den Stream-Fall, und auch der Dateifall wird asynchron behandelt .

Also ja, Node.js hält an seinen nicht blockierenden Versprechen fest.

Ivo Wetzel
quelle
2
Update: stdout in node.js ist jetzt synchron: groups.google.com/group/nodejs/browse_thread/thread/…
dhruvbird
1
Ich denke, das ist jetzt veraltet: github.com/nodejs/node/issues/3524#issuecomment-151097761
tforgione
@IvoWetzel Ich werde dies jetzt ablehnen müssen, da es veraltet ist.
Evan Carroll
Ich weiß, dass dies veraltet ist und alles, aber Sie sagen "bisher nichts Asynchrones" unmittelbar danach, process.stdout.write()wo write()per Definition asynchron ist ...
Binki
26

console.warn () und console.error () blockieren. Sie werden erst zurückgegeben, wenn die zugrunde liegenden Systemaufrufe erfolgreich waren.

Ja, ein Programm kann beendet werden, bevor alles, was in stdout geschrieben wurde, gelöscht wurde. process.exit () beendet den Knoten sofort, auch wenn noch Schreibvorgänge in stdout in der Warteschlange stehen. Sie sollten console.warn verwenden, um dieses Verhalten zu vermeiden.

Matt Ranney
quelle
1
Dies gilt nicht für Knoten 0.10.25 unter Windows. console.warn()und console.error()haben das gleiche nicht blockierende Verhalten von console.log(). Es gibt sogar ein Paket, um das Problem in Windows zu lösen .
Lucio Paiva
12

Meine Schlussfolgerung nach dem Lesen von Node.js 10. * docs (im Anhang unten). ist, dass Sie console.log für die Protokollierung verwenden können, console.log ist synchron und auf niedriger Ebene implementiert. c. Obwohl console.log synchron ist, verursacht es nur dann kein Leistungsproblem, wenn Sie keine große Datenmenge protokollieren.

(Das folgende Befehlszeilenbeispiel zeigt, dass console.log async und console.error synchron sind. )

Basierend auf Node.js Docs

Die Konsolenfunktionen sind synchron, wenn das Ziel ein Terminal oder eine Datei ist (um verlorene Nachrichten bei vorzeitigem Beenden zu vermeiden) und asynchron, wenn es sich um eine Pipe handelt (um ein längeres Blockieren zu vermeiden).

Das heißt, im folgenden Beispiel blockiert stdout nicht, während stderr blockiert:

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

Im täglichen Gebrauch sollten Sie sich über die blockierende / nicht blockierende Dichotomie keine Sorgen machen, es sei denn, Sie protokollieren große Datenmengen.

Ich hoffe es hilft

doron aviguy
quelle
Was ist eine "große Datenmenge"? Wird es durch die Anzahl der Aufrufe von console.log oder den Gesamtbetrag definiert, der geschrieben wird? Was ist eine riesige 1 KB / ms, 1 MB / ms, 1 GB / ms?
MattG
3

Console.log ist in Windows asynchron, während es unter Linux / Mac synchron ist. Um console.log in Windows synchron zu machen, schreiben Sie diese Zeile am Anfang Ihres Codes wahrscheinlich in die Datei index.js. Jedes console.log nach dieser Anweisung wird vom Interpreter als synchron betrachtet.

if (process.stdout._handle) process.stdout._handle.setBlocking(true);
Ali Azlan
quelle
Linux ist übrigens nicht nur Ubuntu.
Ozanmuyes
Danke, entschuldigen Sie meinen pedantischen Kommentar, aber Debian ist meine Schwachstelle und es scheint, dass jeder, der heutzutage anfängt, Linux zu verwenden, Ubuntu für Linux hält (außer Ihnen, ich weiß, dass Sie keiner von ihnen sind). Ich
wünsche Ihnen