回答:
更新:ノード0.6以降、stdoutは同期されるため、この投稿は廃止されました。
さて、console.log
実際に何をするか見てみましょう。
まず、それはコンソールモジュールの一部です:
exports.log = function() {
process.stdout.write(format.apply(this, arguments) + '\n');
};
したがって、これは単に書式設定を行い、に書き込むだけprocess.stdout
です。これまで非同期ではありません。
process.stdout
遅延初期化される起動時に定義されるゲッターです。説明するためにコメントを追加しました。
.... 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;
});
TTYとUNIXの場合、ここで終了します。これはソケットから継承されます。したがって、ノードが基本的に行うことは、データをソケットにプッシュすることだけであり、その後、端末が残りを処理します。
テストしてみましょう!
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);
結果
....a lot of ones....1111111111111111
wrote 208896 bytes in 17ms
real 0m0.969s
user 0m0.068s
sys 0m0.012s
端末はソケットのコンテンツを出力するのに約1秒必要ですが、ノードはデータを端末にプッシュするのに17ミリ秒しか必要ありません。
同じことがストリームの場合にも当てはまり、ファイルの場合も非同期で処理されます。
だから、はい Node.jsのは、その非ブロックの約束にも当てはまります。
process.stdout.write()
、write()
定義上非同期です…
console.warn()とconsole.error()はブロックしています。基になるシステムコールが成功するまで戻りません。
はい、標準出力に書き込まれたものがすべてフラッシュされる前にプログラムが終了する可能性があります。stdoutへの書き込みがまだキューに入っている場合でも、process.exit()はノードをすぐに終了します。この動作を回避するには、console.warnを使用する必要があります。
console.warn()
とconsole.error()
同じ非ブロッキング動作がありconsole.log()
ます。Windowsの問題を解決するためのパッケージさえあります。
私の結論は、Node.js 10. *のドキュメント(下に添付)を読んだ後です。ロギングにconsole.logを使用できることです。console.logは同期的であり、低レベルのcで実装されます。console.logは同期的ですが、大量のデータをログに記録しない場合のみ、パフォーマンスの問題は発生しません。
(以下のコマンドラインの例は、console.log asyncとconsole.error is syncを示しています)
Node.js Docに基づく
コンソール関数は、宛先が端末またはファイルである場合は同期しており(途中で終了した場合にメッセージが失われないようにします)、パイプである場合は非同期です(長時間ブロックされないようにするため)。
つまり、次の例では、stdrがブロックしている間、stdoutは非ブロックです。
$ node script.js 2> error.log | tee info.log
日常的に使用する場合、大量のデータをログに記録しない限り、ブロック/非ブロックの二分法は心配する必要はありません。
それが役に立てば幸い
Console.logはWindowsでは非同期で、Linux / Macでは同期です。ウィンドウでconsole.logを同期させるには、コードの最初にこの行をおそらくindex.jsファイルに書き込みます。このステートメントの後のconsole.logは、インタープリターによって同期と見なされます。
if (process.stdout._handle) process.stdout._handle.setBlocking(true);