js while(true){}阻止事件循环

时间:2017-06-03 11:05:02

标签: javascript event-loop

 setInterval(function(){console.log("hello")},2000);
 while(true){}

"你好"从来没有打印过。  我认为事件循环运行在一个不同的线程中,但在这里它看起来像是循环'正在阻止事件循环'从执行。 有人可以对此有所了解吗?
我对js非常天真,如果问题太基本,那就很抱歉。

2 个答案:

答案 0 :(得分:5)

你必须明白

浏览器内部如何设置setTimeout?

我将简要解释一下。

  

要详细了解

     

Philip Roberts的事件循环更多detail explanation   在jsconf2014

     

Philip Roberts: What the heck is the event loop anyway?

     

另外,要看到这个过程的实际应用,请查看一个很棒的工具   在loupe

要了解您必须了解javascript中的事件队列。在浏览器中实现了事件队列。每当在js中触发事件时,所有这些事件(如点击等等)都会添加到此队列中。当您的浏览器无法执行任何操作时,它会从队列中获取事件并逐个执行。

现在,当您调用setTimeoutsetInterval时,您的回调会在浏览器中注册到计时器,并在给定时间到期后添加到事件队列中,最终javascript从队列中获取该事件并执行它。

这样做是因为javascript执行是单线程,并且它们一次只能执行一件事。因此,他们无法执行其他JavaScript并跟踪您的计时器。这就是为什么这些计时器在浏览器中注册(浏览器不是单线程),它可以跟踪计时器并在计时器到期后在队列中添加一个事件。

同样发生setInterval只有在这种情况下,事件会在指定的时间间隔后一次又一次地添加到队列中,直到它被清除或浏览器页面刷新为止。

  

注意

     

传递给这些函数的延迟参数是最小延迟   时间来执行回调。这是因为计时器到期后   浏览器将事件添加到要由队列执行的队列中   javascript引擎,但回调的执行取决于你的   事件在队列中的位置以及引擎是单线程的   将逐个执行队列中的所有事件。

因此,当您的其他代码阻塞线程并且没有时间处理队列中的内容时,您的回调有时可能会超过指定的延迟时间。

正如我提到的,javascript是单线程。所以,如果你长时间阻止线程。

喜欢这段代码

while(true) { //infinite loop 
}

您的用户可能会收到一条消息,指出页面无响应

在这里,您的setTimeout事件永远不会执行。

答案 1 :(得分:0)

无阻塞的while循环:

let done = false;

setTimeout(() => {
  done = true
}, 5);

const eventLoopQueue = () => {
  return new Promise(resolve => 
    setImmediate(() => {
      console.log('event loop');
      resolve();
    })
  );
}

const run = async () => {
  while (!done) {
    console.log('loop');
    await eventLoopQueue();
  }
}

run().then(() => console.log('Done'));