node.jsのconsole.logは非同期ですか?


95

あるconsole.log/debug/warn/errorNode.jsのasynchrounousに?内容が画面に印刷されるまでJavaScriptコードの実行が停止するのですか、それとも後の段階で印刷されるのですか?

また、ノードがクラッシュした直後のステートメントでconsole.logが何も表示しない可能性があるかどうかを知りたいと思っています。

回答:


102

更新:ノード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のは、その非ブロックの約束にも当てはまります。


2
アップデート:Node.jsの中stdoutが今同期している:groups.google.com/group/nodejs/browse_thread/thread/...
dhruvbird

1
これはもう時代遅れだと思います:github.com/nodejs/node/issues/3524#issuecomment-151097761
tforgione

@IvoWetzel廃止されたので、今はこれに反対投票する必要があります。
エヴァンキャロル

私はこれが時代遅れですべてであることを知っていますが、あなたは「今のところ非同期は何もない」と言っています。その直後にprocess.stdout.write()write()定義上非同期です…
binki

26

console.warn()とconsole.error()はブロックしています。基になるシステムコールが成功するまで戻りません。

はい、標準出力に書き込まれたものがすべてフラッシュされる前にプログラムが終了する可能性があります。stdoutへの書き込みがまだキューに入っている場合でも、process.exit()はノードをすぐに終了します。この動作を回避するには、console.warnを使用する必要があります。


1
これは、Windowsのノード0.10.25には当てはまりません。console.warn()console.error()同じ非ブロッキング動作がありconsole.log()ます。Windowsの問題を解決するためのパッケージさえあります
Lucio Paiva、2014

12

私の結論は、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の呼び出し数または書き込まれる合計量によって定義されますか?巨大な1KB / ms、1MB / ms、1GB / msとは何ですか?
MattG

3

Console.logはWindowsでは非同期で、Linux / Macでは同期です。ウィンドウでconsole.logを同期させるには、コードの最初にこの行をおそらくindex.jsファイルに書き込みます。このステートメントの後のconsole.logは、インタープリターによって同期と見なされます。

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

ちなみに、Linuxは単なるUbuntuではありません。
ozanmuyes

おかげで、私の思いやりのあるコメントは失礼ですが、Debianは私の弱点であり、最近Linuxを使い始めたすべての人は、Ubuntu Linux だと思っているようです(あなたを除いて、私はあなたが彼らの1人ではないことを知っています)。良い一日をお過ごしください:)
ozanmuyes
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.