【发布时间】:2020-06-17 16:04:15
【问题描述】:
我正在研究 Node.js 中 libuv 提供的事件循环。我遇到了following blog by Deepal Jayasekara,也看到了 youtube 上 Bert Belder 和 Daniel Khan 的解释。
有一点我不清楚-根据我的理解,事件循环在进入另一个阶段之前会处理一个阶段的所有项目。因此,如果是这种情况,如果 setTimeout 阶段不断添加回调,我应该能够阻止事件循环。
但是,当我尝试复制它时 - 它没有发生。以下是代码:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('Hello World!');
console.log("Response sent");
res.end();
}).listen(8081);
setInterval(() => {
console.log("Entering for loop");
// Long running loop that allows more callbacks to get added to the setTimeout phase before this callback's processing completes
for (let i = 0; i < 7777777777; i++);
console.log("Exiting for loop");
}, 0);
事件循环似乎以循环方式运行。它首先执行在我向服务器发送请求之前添加的回调,然后处理请求,然后继续回调。感觉就像一个队列正在运行。 据我了解,没有一个队列,所有过期的计时器回调都应该在进入下一阶段之前首先执行。因此上面的 sn-p 应该不能返回 Hello World 响应。
对此有什么可能的解释? 谢谢。
【问题讨论】:
-
仅供参考,定时器的管理方式与其他类型的回调完全不同。计时器系统是事件循环本身的特定部分。
-
这篇文章可能会有所帮助:Understanding the Node.js event loop phases and how it executes the JavaScript code,尤其是“投票”阶段的描述。
-
@jfriend00 事件循环在轮询阶段等待,直到将过期的计时器回调添加到计时器队列/堆中。但是一旦它开始处理计时器回调,它将耗尽整个队列,并且由于我不断添加它,所以循环应该会卡住。除非...在事件循环开始处理之后添加到队列中的回调直到下一次迭代才被考虑。那我想应该是有道理的。或者,如果 http.get() 方法在内部使用了 Promise 或 nextTick。我会对此进行更多研究。很想听听您的意见。
-
我认为计时器到期时不会被添加到队列中。相反,当它在事件循环中时,nodejs 会检查哪个计时器的时间已经过去。这将允许他们仅处理在此事件循环周期开始时触发的计时器,从而使调度更加公平。如果你想在这里了解真正的细节,你必须去看看这部分事件循环的 libuv 代码。
-
好的,我挖了libuv代码,找到了事件循环代码,找到了定时器处理代码,贴出一个答案来解释一下。
标签: javascript node.js event-loop