次のコードでは、data
メソッドを使用してprocess.stdin
のonce
イベントにリスナーを割り当てます。
console.log('Press Enter to allow process to terminate')
process.stdin.once('data', callback)
function callback (data) {
console.log('Process can terminate now')
}
理論的には、コールバックが発生すると、イベントリスナーは自動的に削除され(once
でアタッチしたため)、プロセスを終了できるようになります。驚いたことに、この場合、プロセスは決して終了しません(表示されるコードがすべてです。試してみてください!)。リスナーを手動で削除しようとしましたが、何も変わりません。
おそらく私が気付いていない何かがここで起こっていますか?
data
イベントリスナーを_process.stdin
_に追加すると、プロセスを開いたままにするための参照が追加されます。その参照は、すべてのイベントリスナーを削除した後もそのまま残ります。あなたができることは、次のように、コールバックで手動でunref()
することです。
_console.log('Press Enter to allow process to terminate')
process.stdin.once('data', callback)
function callback (data) {
console.log('Process can terminate now')
process.stdin.unref()
}
_
また、このようなものの一般的なデバッグツールとして、プロセスを開いたままにするもののリストを取得するために呼び出すことができる2つの(文書化されていない)関数があります。
_process._getActiveHandles()
process._getActiveRequests()
_
バックグラウンドについては、ノードプロジェクトの このプルリクエスト を参照してください。
更新:unref()
'd _process.stdin
_を実行した後、イベントリスナーをアタッチすることについて質問しました。これは、リスナーが自分自身と機能をアタッチすることを示す簡単な例です。
_console.log('Press Enter to allow process to terminate')
process.stdin.once('data', callback)
function callback (data) {
console.log('Unreferencing stdin. Exiting in 5 seconds.')
process.stdin.unref()
process.stdin.once('data', function(data) {
console.log('More data')
})
setTimeout(function() {
console.log('Timeout, Exiting.')
}, 5000);
}
_
そのコードでは、setTimeout
が起動する前に(5秒)別のキーを押すと、コンソールに_More data
_出力が表示されます。 setTimeout
のコールバックが発生すると、プロセスは終了します。秘訣は、setTimeout
がタイマーを作成していることです。タイマーはプロセスも参照を保持します。プロセスにはまだ何かへの参照があるため、すぐには終了しません。タイマーが起動すると、タイマーが解放した参照が解放され、プロセスが終了します。これは、参照が自動的に必要なもの(この場合はsetTimeout
によって作成されたタイマー)への参照が追加(および削除)されることも示しています。
.end
ストリームでprocess.stdin
を呼び出すだけです
私にとって、これはストリームを終了するためのより簡単な(そして 文書化された )方法です。
console.log('Press Enter to allow process to terminate');
process.stdin.once('data', callback);
function callback (data) {
console.log('Process can terminate now');
process.stdin.end();
}
ノードがストリームをコールバック関数のコンテキストとして設定することにも注意してください。そのため、this.end
を呼び出すだけで済みます。
console.log('Press Enter to allow process to terminate');
process.stdin.once('data', callback);
function callback (data) {
// `this` refers to process.stdin here
console.log('Process can terminate now');
this.end();
}
end
イベントを発行することもできます。これには、ストリームの終了時に関数を呼び出すことができるなどの追加の利点があります。
console.log('Press Enter to allow process to terminate');
process.stdin.once('data', function(data) {
console.log('Process can terminate now');
this.emit("end");
});
process.stdin.on('end', function() {
console.log("all done now");
});
これは出力します
Press Enter to allow process to terminate
Process can terminate now
all done now
最終的な解決策は、process.exit
を使用することです。これにより、いつでもプログラムを終了できます。
for (var i=0; i<10; i++) {
process.stdout.write( i.toString() );
if (i > 3) process.exit();
}
出力
01234
これは、子プロセスの一部として、またはその他のコードの一部として、ストリームコールバック内で機能します。