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

Jag*_*gga 3 javascript event-loop

 setInterval(function(){console.log("hello")},2000);
 while(true){}
Run Code Online (Sandbox Code Playgroud)

"你好"永远不会被打印出来.我认为事件循环在不同的线程中运行,但是在这里看起来像'while循环'阻止了'事件循环'的执行. 有人可以对此有所了解吗?

我对js非常天真,如果问题太基础,那就很抱歉.

Nad*_*kar 5

你必须明白

浏览器内部如何设置setTimeout?

我将简要解释一下.

要了解更多相关信息

以下是Philip Roberts在jsconf2014中对事件循环的更详细说明

菲利普罗伯茨:无论如何,事件循环到底是什么?

此外,要看到这个过程在行动中有一个很好的工具,看看放大镜

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

现在,当你打电话setTimeoutsetInterval你的回调被注册到浏览器中的计时器,它会在给定的时间到期后被添加到事件队列中,最终javascript从队列中获取事件并执行它.

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

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

注意

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

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

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

喜欢这段代码

while(true) { //infinite loop 
}
Run Code Online (Sandbox Code Playgroud)

您的用户可以得到一个消息,说页面不响应.

在这里,您的setTimeout活动永远不会执行.


Alb*_*rtS 5

非阻塞 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'));
Run Code Online (Sandbox Code Playgroud)