为啥 data 事件只会阻止 NodeJS 运行时退出?

Posted

技术标签:

【中文标题】为啥 data 事件只会阻止 NodeJS 运行时退出?【英文标题】:Why does the data event only stop the NodeJS run time from exiting?为什么 data 事件只会阻止 NodeJS 运行时退出? 【发布时间】:2018-02-05 13:58:59 【问题描述】:

在nodejs-中取如下代码:

console.log("Hello world");
process.stdin.on('connect', function() 

    );

这会打印 Hello World 然后节点退出。但是当我用“数据”事件替换连接事件时,节点运行时不会退出。

这是为什么呢? EventEmitter 的数据事件有什么特别之处?它是否打开套接字连接?所以在 on() 方法中有如下代码 -:

function on(event, callback) 
if(event === 'data') 
     //open socket
     //do work
    
else 
   //do non-socket work
   

是否有一个明确的答案来解释为什么向数据事件添加监听器“神奇地”打开一个套接字。

【问题讨论】:

“数据”事件没有什么特别之处。这是一个与任何其他事件一样的事件。 @ralphtheninja 太好了。那为什么当我们为数据事件附加监听器时nodejs运行时不退出,但当我们为任何其他事件附加监听器时退出 很难说。如果您能显示更多代码,那就太好了。 @ralphtheninja 我正在学习 Node.js。这就是我拥有的所有代码。只需将其粘贴并执行即可。然后将连接切换到数据并查看行为差异 哦,对了。这很可能是process.stdin 的实现细节。 【参考方案1】:

Node.js 事件循环有几个处理阶段,在您的情况下是 poll 阶段。例如传入数据(process.stdin.on('data', cb))的处理,所以直到有一个可以处理这个事件的回调,一个这个事件可能发生,节点事件循环不为空并且节点不会退出。

process.stdin 是具有休闲事件的可读流:

关闭 数据 结束 错误 可读

所以没有像connect 这样的东西。

process.stdin.on('readable', function() 
    console.log('Readable');
);

上面的代码将打印Readable 并退出,因为在触发事件流后,它不处于flowing 状态,因此它将退出事件循环,因为它是空的,但是data 事件将流状态设置为flowing, 因此,如果流状态设置为flowing,并且如果readableState.readingtrue,它将阻止节点退出。 如果你这样做了

process.stdin.on('data', function(data) 
    console.log(data.toString());
);

如果您在运行时在控制台中编写任何内容,它将像 echo 一样工作。

https://github.com/nodejs/node/blob/master/lib/_stream_readable.js#L774-L795

您可以在此处阅读完整说明事件循环的工作原理https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

【讨论】:

从您的回答中我无法理解的是,当我附加一个侦听器时,它为什么要等待接收数据?当我不附加监听器时,什么也没有发生,那么轮询阶段会消失吗?像 fs.readFile 这样的函数实际上做了一些工作然后调用回调,但是为数据事件附加一个监听器什么都不做。那还等什么呢? 还有哪些事件属于poll阶段,哪些事件属于timer阶段。我想我是从错误的角度看待这个问题。能否请您补充一下如何编写 Node 程序的直觉。 那么设置为“流动”的流会阻止节点退出吗? 您可能希望将其添加到您的答案中。【参考方案2】:

如果我们假设 index.js 包含

process.stdin.on('data', console.log)

然后你输入node index.js,然后进程等待stdin 上的输入。

如果您通过例如在标准输入上发送一些数据echo woohoo | node index.js 然后缓冲区将被写入并退出进程。

【讨论】:

以上是关于为啥 data 事件只会阻止 NodeJS 运行时退出?的主要内容,如果未能解决你的问题,请参考以下文章

阻止点击事件

为啥阻止a标签的默认事件

怎么阻止vue的数据更新刷新事件

如何知道是啥阻止了 NodeJS 关闭

为啥要添加“return false;”提交事件阻止页面刷新?

当数据库被播种时,是不是可以阻止 Laravel 运行模型事件?