一个node.js进程如何知道何时停止?

40

由于许多node.js脚本遵循异步执行的模式(如下面的示例),它们如何知道何时停止?

在以下代码中,node是如何确定在处理writeFile并适当地注册回调之后,进程应保持活动状态直到回调运行?

fs = require('fs');

fs.writeFile('foo', 'cat', function() {
  console.log('wrote to foo!'); 
  fs.readFile('foo', 'utf8', function(err, data) {
    console.log(data);
  });
}); 
1个回答

47

Node会追踪所有未完成的工作请求。调用fs.writefile()方法将创建一个I/O工作请求并将回调函数添加到该请求中。当它启动I/O活动时,Node同时将工作请求保存在其表中。执行代码时,当你到达函数的结尾时,代码执行会退出(但你的内存/变量等仍然存在)。

稍后,I/O操作完成时,Node会从其表中取出工作请求。它看到附加到请求的回调函数,因此使用I/O请求的结果调用该函数。全局数据仍然存在,闭包中的任何变量仍然存在,因此你的代码似乎从未停止过。

如果你不再做任何事情,不发出任何更多的请求,则当你从函数中返回时,Node会停止运行,因为此时队列中不再有任何剩余请求。

因此,Node“知道”要继续运行,因为它在其表中跟踪活动工作请求,并且只有在所有排队工作都完成并且这些表为空时才会停止。

请注意,“排队的工作”可以包括等待定时器或等待网络数据到达等内容。你发出的请求是“在稍后某个时间点/如果某些情况发生时请在此处调用我”。

setTimeout()方法也是一个工作请求(如果你稍微想一下的话)。使用定时器,你知道某些事情将发生以及何时发生。而如果使用setTimeout()方法,则只会发生一次“某些事情”。Node将仅调用一次你的回调函数,然后“忘记”该工作请求。如果改为使用setInterval()方法,则创建了一个持久性工作请求。Node将在其表中“保留”该工作请求,并重复调用你的回调函数,直到你取消该请求。

net.Server.listen()方法是另一个持久性工作请求。你不知道何时以及多少次将调用你的回调函数,因为这取决于远程客户端连接到服务器的时间。Node将在其表中保持该工作请求处于活动状态,直到你取消该请求。


15
“工作请求”和“表格”这些概念是您为了阐述观点而创造的,还是它们是 Node 实现中使用的实际构造?我之所以问是因为我在其他地方没有看到过这些术语的使用。 - d512
我相信工作请求被称为任务,而表格被称为任务队列。请参阅https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/。 - Cameron Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接