为什么while循环会阻塞事件循环? [英] Why does a while loop block the event loop?

查看:1117
本文介绍了为什么while循环会阻塞事件循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下示例在Node.js书中给出:

The following example is given in a Node.js book:

var open = false;

setTimeout(function() {
  open = true
}, 1000)

while (!open) {
  console.log('wait');
}

console.log('open sesame');

解释为什么while循环阻止执行,作者说:

Explaining why the while loop blocks execution, the author says:


节点永远不会执行超时回调,因为事件循环是
卡在这个while循环开始于第7行,永远不会给它一个机会
来处理超时事件!

Node will never execute the timeout callback because the event loop is stuck on this while loop started on line 7, never giving it a chance to process the timeout event!

但是,作者没有解释为什么在事件循环的上下文中发生这种情况或者实际发生的事情在引擎盖下。

However, the author doesn't explain why this happens in the context of the event loop or what is really going on under the hood.

有人可以详细说明吗?节点为什么会卡住?如何更改上面的代码,同时保留控制结构,以便不阻止事件循环,代码将按照人们可能合理预期的方式运行;等待
将在 setTimeout 触发之前记录1秒钟,然后该过程在记录'open sesame'后退出。

Can someone elaborate on this? Why does node get stuck? And how would one change the above code, whilst retaining the while control structure so that the event loop is not blocked and the code will behave as one might reasonably expect; wait will be logged for only 1 second before the setTimeout fires and the process then exits after logging 'open sesame'.

通用解释,例如答案这个问题并没有真正帮助我理解这一点。我希望直接引用上述代码的答案会有所帮助。

Generic explanations such as the answers to this question about IO and event loops and callbacks do not really help me rationalise this. I'm hoping an answer which directly references the above code will help.

推荐答案

这真的很简单。在内部,node.js由这种类型的循环组成:

It's fairly simple really. Internally, node.js consists of this type of loop:


  • 从事件队列中获取内容

  • 运行指示的任何任务并运行它直到它返回

  • 完成上述任务后,从事件队列中获取下一个项目

  • 运行任何指示的任务并运行直到它返回

  • 冲洗,泡沫,重复 - 一遍又一遍

  • Get something from the event queue
  • Run whatever task is indicated and run it until it returns
  • When the above task is done, get the next item from the event queue
  • Run whatever task is indicated and run it until it returns
  • Rinse, lather, repeat - over and over

如果在某个时刻,事件队列中没有任何内容,则进入睡眠状态,直到事件队列中放置了某些内容。

If at some point, there is nothing in the event queue, then go to sleep until something is placed in the event queue.

所以,如果一个Javascript位于而()循环中,那么该任务没有完成,按照上面的顺序,没有什么新的从事件队列中挑选出来,直到完成上一个任务。因此,非常长或永远在运行的 while()循环只是粗略的工作。因为Javascript一次只运行一个任务(JS执行单线程),如果那个任务在while循环中旋转,那么其他任何东西都无法执行。

So, if a piece of Javascript is sitting in a while() loop, then that task is not finishing and per the above sequence, nothing new will be picked out of the event queue until that prior task is completely done. So, a very long or forever running while() loop just gums up the works. Because Javascript only runs one task at a time (single threaded for JS execution), if that one task is spinning in a while loop, then nothing else can ever execute.

这是一个可能有助于解释它的简单示例:

Here's a simple example that might help explain it:

 var done = false;

 // set a timer for 1 second from now to set done to true
 setTimeout(function() {
      done = true;
 }, 1000);

 // spin wait for the done value to change
 while (!done) { /* do nothing */}

 console.log("finally, the done value changed!");

有些人可能从逻辑上认为while循环会旋转直到计时器触发,然后计时器将改变值完成 true 然后while循环结束, console.log( )最后将执行。那不会发生什么。这实际上是一个无限循环, console.log()语句永远不会执行。

Some might logically think that the while loop will spin until the timer fires and then the timer will change the value of done to true and then the while loop will finish and the console.log() at the end will execute. That is NOT what will happen. This will actually be an infinite loop and the console.log() statement will never be executed.

问题一旦你在 while()循环中进入旋转等待,没有其他Javascript可以执行。因此,想要更改 done 变量值的计时器无法执行。因此,while循环条件永远不会改变,因此它是一个无限循环。

The issue is that once you go into the spin wait in the while() loop, NO other Javascript can execute. So, the timer that wants to change the value of the done variable cannot execute. Thus, the while loop condition can never change and thus it is an infinite loop.

这是JS引擎内部发生的事情:

Here's what happens internally inside the JS engine:


  1. 已完成变量初始化为 false

  2. setTimeout()从现在起安排计时器事件1秒

  3. while循环开始旋转

  4. 进入while循环旋转1秒钟,计时器在内部触发JS引擎,计时器回调被添加到事件队列中。这可能发生在JS引擎内部的不同线程上。

  5. while循环不断旋转,因为 done 变量永远不会改变。因为它继续旋转,JS引擎永远不会完成这个执行线程,永远不会从事件队列中提取下一个项目。

  1. done variable initialized to false
  2. setTimeout() schedules a timer event for 1 second from now
  3. The while loop starts spinning
  4. 1 second into the while loop spinning, the timer fires internally to the JS engine and the timer callback is added to the event queue. This likely occurs on a different thread, internal to the JS engine.
  5. The while loop keeps spinning because the done variable never changes. Because it continues to spin, the JS engine never finishes this thread of execution and never gets to pull the next item from the event queue.

这篇关于为什么while循环会阻塞事件循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆