2011-10-08 24 views
36

由于许多node.js脚本遵循异步执行某些操作的模式(如下所示),他们如何知道何时停止?node.js过程如何知道何时停止?

在下面的代码中,节点在处理writeFile之后如何确定并正确注册回调,该过程应保持活动状态,直到回调(s)运行?

fs = require('fs'); 

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

回答

40

节点跟踪所有未解决的工作请求。您的fs.writefile()调用将为I/O创建一个工作请求,并将您的回调添加到该请求中。节点在开始I/O活动的同时将工作请求保存到其表中。您的代码执行在您的函数结束时退出。 (但你的内存/变量/等仍然存在)

后来I/O完成,节点将工作请求从其表中取出。它看到附加到该请求的回调函数,因此调用这些函数以及I/O请求的结果。您的全局数据仍然存在,并且任何闭包中的变量仍然存在,因此您的代码似乎从未停止过。

如果你什么都不做,不要再做任何请求,那么当你从你的函数返回时,节点将停止,因为那么队列中就不会有任何剩余的请求。

因此节点'知道'继续运行,因为它跟踪其表中的活动工作请求,并且不会停止,直到所有排队工作完成并且这些表为空。

请注意,“排队工作”可能包括诸如等待定时器或等待网络数据到达等事情。你提出一个请求,说“稍后发生/如果有事情发生,请给我打电话”。

setTimeout()也是一个工作请求(如果你眯了一下)。有了计时器,你知道会发生什么事情,什么时候会发生。通过setTimeout(),只有一个'东西'会发生。节点只会对您的回调进行一次调用,然后“忘记”工作请求。如果您使用setInterval(),则您创建了一个持久工作请求。节点会将工作请求“保留”在其表中,并将重复调用您的回调,直到您取消请求。

net.Server.listen()是另一个工作请求,它是一个持久工作请求。您不知道何时会调用回调或多少次,因为这取决于连接到服务器的远程客户端。节点将工作请求保持在其表中,直到您取消请求。

+15

工作请求和表的概念是你制定的一些事情来说明你的观点还是这些实际结构用于实施节点?我问,因为我没有看到其他地方使用这些术语。 – d512

+0

我相信工作请求被称为任务,表格被称为任务队列。请参阅https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ –

相关问题