setInterval(function(){console.log("hello")},2000);
while(true){}
"你好"从来没有打印过。
我认为事件循环运行在一个不同的线程中,但在这里它看起来像是循环'正在阻止事件循环'从执行。
有人可以对此有所了解吗?
我对js非常天真,如果问题太基本,那就很抱歉。
答案 0 :(得分:5)
你必须明白
浏览器内部如何设置setTimeout?
我将简要解释一下。
要详细了解
Philip Roberts的事件循环更多detail explanation 在jsconf2014
Philip Roberts: What the heck is the event loop anyway?
另外,要看到这个过程的实际应用,请查看一个很棒的工具 在loupe
要了解您必须了解javascript中的事件队列。在浏览器中实现了事件队列。每当在js中触发事件时,所有这些事件(如点击等等)都会添加到此队列中。当您的浏览器无法执行任何操作时,它会从队列中获取事件并逐个执行。
现在,当您调用setTimeout
或setInterval
时,您的回调会在浏览器中注册到计时器,并在给定时间到期后添加到事件队列中,最终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'));