console.log de node.js est-il asynchrone?

95

Est-ce que console.log/debug/warn/errordans node.js est asynchrone? Je veux dire que l'exécution du code javascript s'arrêtera jusqu'à ce que le contenu soit imprimé à l'écran ou sera-t-il imprimé à un stade ultérieur?

En outre, je suis intéressé de savoir s'il est possible pour un console.log de NE PAS afficher quoi que ce soit si l'instruction immédiatement après qu'elle plante le nœud.

dhruvbird
la source

Réponses:

102

Mise à jour: à partir de Node 0.6, ce post est obsolète, car stdout est désormais synchrone .

Eh bien, voyons ce que console.logfait réellement.

Tout d'abord, il fait partie du module de console :

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

Donc, il fait simplement du formatage et écrit process.stdout, rien de asynchrone jusqu'à présent.

process.stdoutest un getter défini au démarrage qui est initialisé paresseusement, j'ai ajouté quelques commentaires pour expliquer les choses:

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

Dans le cas d'un TTY et UNIX, nous nous retrouvons ici , cette chose hérite de socket. Donc, tout ce que fait ce nœud est essentiellement de pousser les données sur la socket, puis le terminal s'occupe du reste.

Testons-le!

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

Résultat

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

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

Le terminal a besoin d'environ 1 seconde pour imprimer le contenu des sockets, mais le nœud n'a besoin que de 17 millisecondes pour pousser les données vers le terminal.

Il en va de même pour le cas de flux, et le cas de fichier est également traité de manière asynchrone .

Alors oui, Node.js tient ses promesses non bloquantes.

Ivo Wetzel
la source
2
Mise à jour: stdout dans node.js est maintenant synchrone: groups.google.com/group/nodejs/browse_thread/thread/…
dhruvbird
1
Je pense que c'est obsolète maintenant: github.com/nodejs/node/issues/3524#issuecomment-151097761
tforgione
@IvoWetzel Je vais devoir voter contre cela maintenant car il est obsolète.
Evan Carroll
Je sais que c'est obsolète et tout, mais vous dites «rien d'asynchrone jusqu'à présent» immédiatement après process.stdout.write()write()est par définition asynchrone…
binki
26

console.warn () et console.error () bloquent. Ils ne reviennent que lorsque les appels système sous-jacents ont réussi.

Oui, il est possible pour un programme de se fermer avant que tout ce qui est écrit sur stdout n'ait été vidé. process.exit () terminera immédiatement le nœud, même s'il y a encore des écritures en file d'attente sur stdout. Vous devez utiliser console.warn pour éviter ce comportement.

Matt Ranney
la source
1
Ce n'est pas vrai pour Node 0.10.25 dans Windows. console.warn()et console.error()ont le même comportement non bloquant que console.log(). Il existe même un package pour résoudre le problème sous Windows .
Lucio Paiva
12

Ma conclusion, après avoir lu Node.js 10. * docs (ci-dessous). est que vous pouvez utiliser console.log pour la journalisation, console.log est synchrone et implémenté en bas niveau c. Bien que console.log soit synchronisé, il ne causera pas de problème de performances uniquement si vous n'enregistrez pas d'énormes quantités de données.

(L'exemple de ligne de commande ci-dessous montre, console.log async et console.error est sync )

Basé sur Node.js Doc's

Les fonctions de la console sont synchrones lorsque la destination est un terminal ou un fichier (pour éviter la perte de messages en cas de sortie prématurée) et asynchrones lorsqu'il s'agit d'un tube (pour éviter de bloquer pendant de longues périodes).

Autrement dit, dans l'exemple suivant, stdout est non bloquant tandis que stderr bloque:

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

Dans une utilisation quotidienne, la dichotomie bloquant / non bloquant n'est pas quelque chose dont vous devriez vous inquiéter à moins que> vous n'enregistriez d'énormes quantités de données.

J'espère que ça aide

Doron Aviguy
la source
Qu'est-ce qu'une «énorme quantité de données»? Est-il défini par le nombre d'appels à console.log ou le montant total en cours d'écriture? Qu'est-ce qu'un énorme 1 Ko / ms, 1 Mo / ms, 1 Go / ms?
MattG
3

Console.log est asynchrone dans Windows alors qu'il est synchrone sous linux / mac. Pour rendre console.log synchrone dans Windows, écrivez cette ligne au début de votre code probablement dans le fichier index.js. Tout console.log après cette instruction sera considéré comme synchrone par l'interpréteur.

if (process.stdout._handle) process.stdout._handle.setBlocking(true);
Ali Azlan
la source
Au fait, Linux n'est pas seulement ubuntu.
ozanmuyes
Merci, excusez mon commentaire pédant , mais Debian est mon point faible et il semble que tout le monde qui a commencé à utiliser Linux pense aujourd'hui Ubuntu est Linux (sauf vous, je sais que vous n'êtes pas l' un d'entre eux). Passez une bonne journée :)
ozanmuyes