console.log di node.js è asincrono?


95

Sono console.log/debug/warn/errorin node.js asincroni? Voglio dire, l'esecuzione del codice javascript si interromperà fino a quando il materiale non verrà stampato sullo schermo o verrà stampato in una fase successiva?

Inoltre, mi interessa sapere se è possibile che un console.log NON visualizzi nulla se l'istruzione immediatamente dopo l'arresto anomalo del nodo.

Risposte:


102

Aggiornamento: a partire dal nodo 0.6 questo post è obsoleto, poiché ora lo stdout è sincrono .

Bene, vediamo cosa console.logfa effettivamente.

Prima di tutto fa parte del modulo console :

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

Quindi fa semplicemente un po 'di formattazione e scrive su process.stdout, niente di asincrono finora.

process.stdoutè un getter definito all'avvio che viene inizializzato pigramente, ho aggiunto alcuni commenti per spiegare le cose:

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

In caso di TTY e UNIX finiamo qui , questa cosa eredita da socket. Quindi tutto ciò che il nodo fa fondamentalmente è inviare i dati al socket, quindi il terminale si occupa del resto.

Proviamolo!

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

Risultato

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

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

Il terminale impiega circa 1 secondo per stampare il contenuto dei socket, ma il nodo necessita solo di 17 millisecondi per inviare i dati al terminale.

Lo stesso vale per il caso di flusso e anche il caso di file viene gestito in modo asincrono .

Quindi sì, Node.js mantiene le sue promesse di non blocco.


2
Aggiornamento: lo stdout in node.js è ora sincrono: groups.google.com/group/nodejs/browse_thread/thread/…
dhruvbird


@IvoWetzel Dovrò sottoporlo a un voto negativo ora perché è obsoleto.
Evan Carroll

So che è obsoleto e tutto, ma dici "niente di asincrono finora" immediatamente dopo process.stdout.write()dove write()è per definizione asincrono ...
binki

26

console.warn () e console.error () si stanno bloccando. Non vengono restituiti finché le chiamate di sistema sottostanti non hanno avuto esito positivo.

Sì, è possibile che un programma esca prima che tutto ciò che è scritto su stdout sia stato scaricato. process.exit () terminerà immediatamente il nodo, anche se ci sono ancora scritture in coda su stdout. Dovresti usare console.warn per evitare questo comportamento.


1
Questo non è vero per il nodo 0.10.25 in Windows. console.warn()e console.error()hanno lo stesso comportamento non bloccante di console.log(). C'è anche un pacchetto per risolvere il problema in Windows .
Lucio Paiva

12

La mia conclusione, dopo aver letto i documenti di Node.js 10. * (allegati sotto). è che puoi usare console.log per la registrazione, console.log è sincrono e implementato a basso livello c. Sebbene console.log sia sincronico, non causerà problemi di prestazioni solo se non si registrano enormi quantità di dati.

(L'esempio della riga di comando seguente mostra, console.log async e console.error is sync )

Basato su Node.js Doc's

Le funzioni della console sono sincrone quando la destinazione è un terminale o un file (per evitare la perdita di messaggi in caso di uscita prematura) e asincrone quando è una pipe (per evitare blocchi per lunghi periodi di tempo).

Cioè, nel seguente esempio, stdout non blocca mentre stderr sta bloccando:

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

Nell'uso quotidiano, la dicotomia blocco / non blocco non è qualcosa di cui ti dovresti preoccupare a meno che tu non> registri enormi quantità di dati.

Spero che sia d'aiuto


Che cos'è una "quantità enorme di dati"? È definito dal numero di chiamate a console.log o dall'importo totale scritto? Che cos'è un enorme 1 KB / ms, 1 MB / ms, 1 GB / ms?
MattG

3

Console.log è asincrono in Windows mentre è sincrono in linux / mac. Per rendere sincrono console.log in Windows scrivi questa riga all'inizio del codice probabilmente nel file index.js. Qualsiasi console.log dopo questa istruzione verrà considerato sincrono dall'interprete.

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

Linux non è solo Ubuntu, comunque.
ozanmuyes

Grazie, scusa il mio commento pedante ma Debian è il mio punto debole e sembra che tutti quelli che hanno iniziato a usare Linux oggigiorno pensino che Ubuntu sia Linux (tranne te, so che non sei uno di loro). Buona giornata :)
ozanmuyes
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.