web-dev-qa-db-ja.com

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

console.log/debug/warn/error node.jsで非同期ですか?つまり、JavaScriptコードの実行は、画面に印刷されるまで停止しますか、それとも後の段階で印刷されますか?

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

88
dhruvbird

更新:Node 0.6から始まり、stdoutはsynchronous今。

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の場合、最終的に here になり、このことはソケットから継承します。そのため、ノードが基本的に行うことは、データをソケットにプッシュすることだけです。その後、ターミナルが残りを処理します。

テストしてみましょう!

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ミリ秒しか必要としません。

同じことがストリームの場合にも当てはまり、ファイルの場合もハンドル 非同期 を取得します。

そのため、yesNode.jsは、非ブロッキングの約束を守ります。

97
Ivo Wetzel

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

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

26
Matt Ranney

Node.js 10. *のドキュメント(以下に添付)を読んだ後の私の結論。ロギングにconsole.logを使用できることです。console.logは同期され、低レベルcで実装されます。 console.logは同期的ですが、大量のデータをログに記録していない場合にのみパフォーマンスの問題は発生しません。

(以下のコマンドラインの例は、console.logasyncを示し、console.errorはsync

Node.js Doc's に基づく

コンソール関数は、宛先が端末またはファイルの場合(早期終了の場合にメッセージが失われないようにするため)に同期し、パイプの場合に非同期(長期間ブロックしないようにするため)です。

つまり、次の例では、stderrがブロックしている間、stdoutは非ブロックです。

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

毎日の使用では、大量のデータをログに記録しない限り、ブロッキング/ノンブロッキングの二分法は心配する必要はありません。

それが役に立てば幸い

11
doron aviguy

Console.logはWindowsでは非同期ですが、linux/macでは同期です。 Windowsでconsole.logを同期するには、おそらくindex.jsファイルでコードの先頭にこの行を記述します。このステートメントの後のconsole.logは、インタープリターによって同期と見なされます。

if (process.stdout._handle) process.stdout._handle.setBlocking(true);
3
Ali Azlan