Sont console.log/debug/warn/error
dans node.js asynchrounous? Je veux dire, l'exécution du code javascript s'arrêtera-t-elle jusqu'à ce que le contenu soit imprimé à l'écran ou s'imprimera-t-il à un stade ultérieur?
En outre, je suis intéressé de savoir s'il est possible pour un console.log de ne rien afficher si l'instruction immédiatement après avoir bloqué le nœud.
Mise à jour: À partir de Node 0.6 ce post est obsolète, car stdout est synchrone = maintenant.
Voyons ce que console.log
en fait.
Tout d'abord, il fait partie du module console :
exports.log = function() {
process.stdout.write(format.apply(this, arguments) + '\n');
};
Il effectue donc simplement un formatage et écrit dans process.stdout
, rien d'asynchrone jusqu'à présent.
process.stdout
est un getter défini au démarrage qui est paresseusement initialisé, 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 le nœud est de pousser les données sur le 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 transmettre les données au terminal.
Il en va de même pour le cas du flux, et aussi le cas du fichier obtient handle asynchrone .
Donc oui Node.js tient ses promesses non bloquantes.
console.warn () et console.error () bloquent. Ils ne reviennent que lorsque les appels système sous-jacents ont réussi.
Oui, il est possible qu'un programme se termine avant que tout ce qui est écrit sur stdout n'ait été vidé. process.exit () terminera le noeud immédiatement, même s'il y a encore des écritures en file d'attente sur stdout. Vous devez utiliser console.warn pour éviter ce comportement.
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 synchronique, il ne causera pas de problème de performances uniquement si vous ne connectez pas une énorme quantité 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 les messages perdus en cas de sortie prématurée) et asynchrones lorsqu'il s'agit d'un canal (pour éviter le blocage pendant de longues périodes).
Autrement dit, dans l'exemple suivant, stdout ne bloque pas tandis que stderr bloque:
$ node script.js 2> error.log | tee info.log
Dans une utilisation quotidienne, la dichotomie bloquante/non bloquante n'est pas quelque chose dont vous devriez vous soucier à moins que vous ne consigniez d'énormes quantités de données.
J'espère que ça aide
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);