所有侦听器都删除后,为什么我的Node.js进程不终止? [英] Why doesn't my Node.js process terminate once all listeners have been removed?
问题描述
在下面的代码中,我使用once
方法将侦听器分配给process.stdin
的data
事件.
In the following code, I assign a listener to the data
event of process.stdin
with the once
method.
console.log('Press Enter to allow process to terminate')
process.stdin.once('data', callback)
function callback (data) {
console.log('Process can terminate now')
}
理论上,触发回调后,应自动删除事件侦听器(因为我将它附加到了once
),从而允许进程终止.令人惊讶的是,在这种情况下,该过程永远不会终止(您所看到的代码是完整的,请尝试!).我还尝试过手动删除侦听器,但这没有任何改变.
In theory, when the callback has fired, the event listener should be automatically removed (because I attached it with once
), allowing the process to terminate. Surprisingly, in this case, the process never terminates (The code you see is the whole thing, try it!). I also tried manually removing the listener, but that changes nothing.
这里还有其他我可能没有意识到的事情吗?
Is there something else going on here that I don't realise perhaps?
推荐答案
将data
事件侦听器添加到process.stdin
会添加对它的引用,以使进程保持打开状态.即使删除了所有事件侦听器,该引用也会保留在原位.您可以做的是在回调中手动unref()
,如下所示:
Adding the data
event listener to process.stdin
add a reference to it that keeps the process open. That reference stays in place even after removing all event listeners. What you can do is manually unref()
it in your callback, like so:
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()
}
此外,作为用于此类操作的常规调试工具,您可以调用两个(未记录的)函数来获取使进程保持打开状态的列表:
Also, as a general debugging tool for stuff like this, there are two (undocumented) functions that you can call to get a list of things keeping your process open:
process._getActiveHandles()
process._getActiveRequests()
请参阅节点项目中的此提取请求背景.
更新:您问过unref()
process.stdin
后是否附加事件监听器.这是一个简单的示例,显示了侦听器确实附加了自身并起作用:
Update: You asked about attaching event listeners after you've unref()
'd process.stdin
. Here's a quick example showing that the listener does attach itself and function:
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
创建的计时器).
With that code, if you press another key before the setTimeout
fires (5 seconds), then you'll see More data
output to the console. Once the setTimeout
's callback fires, the process will exit. The trick is that setTimeout
is creating a timer which the process also keeps a reference too. Since the process still has a reference to something, it won't exit right away. Once the timer fires, the reference it released and the process exits. This also shows that references are added (and removed) to things that need them automatically (the timer created by setTimeout
in this case).
这篇关于所有侦听器都删除后,为什么我的Node.js进程不终止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!