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

js while(true){} blocks event loop

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

“你好”永远不会被打印出来。

我认为事件循环在不同的线程中运行,但这里似乎 'while loop' 阻止了 'event loop' 的执行。 有人可以解释一下吗?

你要明白

浏览器内部如何设置超时?

我简单说明一下。

To learn more about this

Here is more detail explanation of event loop by Philip Roberts in jsconf2014

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

Also, to see this process in action there is a great tool take a look at loupe

要了解您必须了解 javascript 中的事件队列。浏览器中实现了事件队列。每当在 js 中触发事件时,所有这些事件(如点击等)都会添加到此队列中。当你的浏览器没有什么可执行的时候,它会从队列中取出一个事件并一个一个地执行它们。

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

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

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

Note

The delay parameter you pass to these functions is the minimum delay time to execute the callback. This is because after the timer expires the browser adds the event to the queue to be executed by the javascript engine but the execution of the callback depends upon your events position in the queue and as the engine is single threaded it will execute all the events in the queue one by one.

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

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

喜欢这个代码

while(true) { //infinite loop 
}

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

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

非阻塞 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'));