¿Es node.js 'console.log asincrónico?

95

¿ console.log/debug/warn/errorSon asíncronos en node.js? Quiero decir, ¿se detendrá la ejecución del código javascript hasta que el material se imprima en la pantalla o se imprimirá en una etapa posterior?

Además, estoy interesado en saber si es posible que un console.log NO muestre nada si la declaración inmediatamente después de que se bloquea el nodo.

dhruvbird
fuente

Respuestas:

102

Actualización: a partir del Nodo 0.6, esta publicación es obsoleta, ya que stdout ahora es sincrónico .

Bueno, veamos lo que console.logrealmente hace.

En primer lugar, es parte del módulo de la consola :

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

Así que simplemente formatea y escribe process.stdout, nada asincrónico hasta ahora.

process.stdoutes un captador definido en el inicio que se inicializa de manera perezosa, he agregado algunos comentarios para explicar las cosas:

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

En el caso de TTY y UNIX terminamos aquí , esto hereda de socket. Entonces, todo lo que hace básicamente ese nodo es enviar los datos al socket, luego el terminal se encarga del resto.

¡Probémoslo!

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

Resultado

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

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

El terminal necesita alrededor de 1 segundo para imprimir el contenido de los sockets, pero el nodo solo necesita 17 milisegundos para enviar los datos al terminal.

Lo mismo ocurre con el caso de transmisión, y también el caso del archivo se maneja de forma asincrónica .

Entonces, sí, Node.js se mantiene fiel a sus promesas de no bloqueo.

Ivo Wetzel
fuente
2
Actualización: stdout en node.js ahora es sincrónico: groups.google.com/group/nodejs/browse_thread/thread/…
dhruvbird
1
Creo que esto es obsoleto ahora: github.com/nodejs/node/issues/3524#issuecomment-151097761
tforgione
@IvoWetzel Voy a tener que rechazar esto ahora, ya que está obsoleto.
Evan Carroll
Sé que esto es obsoleto y todo, pero dices "nada asincrónico hasta ahora" inmediatamente después de process.stdout.write()donde write()es, por definición, asincrónico ...
binki
26

console.warn () y console.error () están bloqueando. No regresan hasta que las llamadas al sistema subyacente se hayan realizado correctamente.

Sí, es posible que un programa se cierre antes de que todo lo escrito en stdout se haya eliminado. process.exit () terminará el nodo inmediatamente, incluso si todavía hay escrituras en cola en stdout. Debe usar console.warn para evitar este comportamiento.

Matt Ranney
fuente
1
Esto no es cierto para el nodo 0.10.25 en Windows. console.warn()y console.error()tienen el mismo comportamiento sin bloqueo de console.log(). Incluso hay un paquete para resolver el problema en Windows .
Lucio Paiva
12

Mi conclusión, después de leer Node.js 10. * docs (adjunto a continuación). es que puede usar console.log para el registro, console.log es síncrono y está implementado en nivel bajo c. Aunque console.log es sincrónico, no causará un problema de rendimiento solo si no registra una gran cantidad de datos.

(El siguiente ejemplo de línea de comando demuestra, console.log async y console.error es sync )

Basado en Node.js Doc's

Las funciones de la consola son síncronas cuando el destino es un terminal o un archivo (para evitar la pérdida de mensajes en caso de salida prematura) y asíncronas cuando es un pipe (para evitar bloqueos por largos períodos de tiempo).

Es decir, en el siguiente ejemplo, stdout no bloquea mientras que stderr bloquea:

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

En el uso diario, la dicotomía bloqueo / no bloqueo no es algo de lo que deba preocuparse a menos que registre grandes cantidades de datos.

Espero eso ayude

doron aviguy
fuente
¿Qué es una "gran cantidad de datos"? ¿Está definido por la cantidad de llamadas a console.log o la cantidad total que se está escribiendo? ¿Qué es un enorme 1KB / ms, 1MB / ms, 1GB / ms?
MattG
3

Console.log es asíncrono en Windows mientras que lo es en linux / mac. Para hacer que console.log sea sincrónico en Windows, escribe esta línea al comienzo de tu código, probablemente en el archivo index.js. Cualquier console.log después de esta declaración será considerado sincrónico por el intérprete.

if (process.stdout._handle) process.stdout._handle.setBlocking(true);
Ali Azlan
fuente
Linux no es solo ubuntu por cierto.
ozanmuyes
Gracias, disculpe mi comentario pedante pero Debian es mi punto débil y parece que todos los que empezaron a usar Linux hoy en día piensan que Ubuntu es Linux (excepto usted, sé que no es uno de ellos). Que tengas un buen día :)
ozanmuyes