Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript nodejs(libuv)事件循环是在移动到下一个阶段(队列)之前在一个阶段(队列)中执行所有回调,还是以循环方式运行?_Javascript_Node.js_Event Loop - Fatal编程技术网

Javascript nodejs(libuv)事件循环是在移动到下一个阶段(队列)之前在一个阶段(队列)中执行所有回调,还是以循环方式运行?

Javascript nodejs(libuv)事件循环是在移动到下一个阶段(队列)之前在一个阶段(队列)中执行所有回调,还是以循环方式运行?,javascript,node.js,event-loop,Javascript,Node.js,Event Loop,我正在研究节点中libuv提供的事件循环。我在youtube上看到了Bert Belder和Daniel Khan的解释 有一点我不清楚——根据我的理解,事件循环在进入另一个阶段之前处理一个阶段的所有项目。因此,如果是这种情况,我应该能够阻止事件循环,如果setTimeout阶段不断添加回调 然而,当我试图复制它时,它没有发生。代码如下: var http = require('http'); http.createServer(function (req, res) { res.writ

我正在研究节点中libuv提供的事件循环。我在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);
var http=require('http');
http.createServer(函数(req,res){
res.writeHead(200,{'Content-Type':'text/plain'});
res.write(“你好,世界!”);
控制台日志(“已发送响应”);
res.end();
}).听(8081);
设置间隔(()=>{
console.log(“为循环输入”);
//长时间运行的循环,允许在此回调处理完成之前将更多回调添加到setTimeout阶段
for(设i=0;i<7777;i++);
log(“退出循环”);
}, 0);
事件循环似乎以循环方式运行。它首先执行在我向服务器发送请求之前添加的回调,然后处理请求,然后继续回调。感觉好像只有一个队列在运行。 据我所知,这里没有一个队列,所有过期的计时器回调都应该在进入下一阶段之前先执行。因此,上面的代码片段应该不能返回Hello World响应

对此可能的解释是什么?
谢谢。

如果您查看libuv本身,您会发现事件循环中运行计时器的操作部分是函数

它的工作方式是,事件循环在当前时间设置一个时间标记,然后依次处理该时间到期的所有计时器,而不更新循环时间。因此,这将触发所有已经过期的计时器,但不会在处理已经到期的计时器时触发任何新的到期计时器

这将导致更公平的调度,因为它运行所有到期的计时器,然后运行事件循环中其余类型的事件,然后返回来执行任何更多到期的计时器。这将不会处理在此事件循环周期开始时未到期但在处理其他计时器时到期的任何计时器。因此,您可以看到您询问的行为

使用以下代码从事件循环的中调用上述函数:

int uv_run(uv_loop_t *loop, uv_run_mode mode) {
  DWORD timeout;
  int r;
  int ran_pending;

  r = uv__loop_alive(loop);
  if (!r)
    uv_update_time(loop);

  while (r != 0 && loop->stop_flag == 0) {
    uv_update_time(loop);                    <==  establish loop time
    uv__run_timers(loop);                    <==  process only timers due by that loop time

    ran_pending = uv_process_reqs(loop);
    uv_idle_invoke(loop);
    uv_prepare_invoke(loop);

 .... more code here

}

当事件循环进入 给定阶段,它将执行特定于该阶段的任何操作, 然后在该阶段的队列中执行回调,直到该队列被调用为止 已耗尽或执行了最大数量的回调。当 队列已用尽或已达到回调限制,事件 循环将移动到下一阶段,依此类推

也是从

当延迟大于2147483647或小于1时,延迟将设置为1

现在,当您运行代码段时,会发生以下情况:

  • 脚本执行开始,回调被注册到特定阶段。此外,正如文档所示,setInterval延迟隐式转换为1秒
  • 1秒后,将执行
    setInterval
    回调,它将阻止eventloop,直到所有迭代完成。同时,在循环终止之前,eventloop不会收到任何传入请求的通知
  • 一旦所有迭代完成,并且有1秒的超时,轮询阶段将执行HTTP请求回调(如果有)
  • 回到步骤2

  • 仅供参考,计时器的管理与其他类型的回调完全不同。计时器系统是事件循环本身的一个特定部分。本文可能会有所帮助:,特别是“轮询”阶段的描述。@jfriend00事件循环在轮询阶段等待,直到过期的计时器回调被添加到计时器队列/堆。但一旦它开始处理计时器回调,它将耗尽整个队列,因为我一直在添加它,循环应该会卡住。除非。。。在事件循环开始处理队列后添加到队列中的回调直到下一次迭代才会考虑。那么我想这是有道理的。或者如果http.get()方法在内部使用Promissions或nextTick。我将对此进行更多研究。我很想听听你的意见。我不认为计时器过期时会加入队列。相反,当它在事件循环中时,nodejs会检查哪个计时器的时间已经过去。这将允许他们只处理在事件循环周期开始时触发的计时器,从而使调度更加公平。如果您想了解这里的真实细节,您必须查看事件循环这一部分的libuv代码。好的,我深入libuv代码,找到了事件循环代码,找到了计时器处理代码,并发布了解释它的答案。超级!谢谢:)
    int uv_run(uv_loop_t *loop, uv_run_mode mode) {
      DWORD timeout;
      int r;
      int ran_pending;
    
      r = uv__loop_alive(loop);
      if (!r)
        uv_update_time(loop);
    
      while (r != 0 && loop->stop_flag == 0) {
        uv_update_time(loop);                    <==  establish loop time
        uv__run_timers(loop);                    <==  process only timers due by that loop time
    
        ran_pending = uv_process_reqs(loop);
        uv_idle_invoke(loop);
        uv_prepare_invoke(loop);
    
     .... more code here
    
    }
    
    void uv_update_time(uv_loop_t* loop) {
      uint64_t new_time = uv__hrtime(1000);
      assert(new_time >= loop->time);
      loop->time = new_time;
    }