Web 浏览器中的事件循环
绝大多数现代 JavaScript 环境都根据事件循环工作。这是计算机编程中的一个常见概念,这实际上意味着你的程序不断地等待新事物发生,并且当它们发生时,会对它们做出反应。在主机环境调用到你的程序,在产卵事件循环,然后一个转或嘀或任务 运行完成。当转弯完成后,主机环境会在所有这一切开始之前等待其他事情发生。
一个简单的例子就是在浏览器中。请考虑以下示例:
<!DOCTYPE html>
<title>Event loop example</title>
<script>
console.log("this a script entry point");
document.body.onclick = () => {
console.log("onclick");
};
setTimeout(() => {
console.log("setTimeout callback log 1");
console.log("setTimeout callback log 2");
}, 100);
</script>
在此示例中,主机环境是 Web 浏览器。
- HTML 解析器将首先执行
<script>
。它将运行完成。 - 对
setTimeout
的调用告诉浏览器,在 100 毫秒之后,它应该将任务排队以执行给定的操作。 - 与此同时,事件循环负责不断检查是否还有其他事情要做:例如,渲染网页。
- 在 100 毫秒之后,如果事件循环由于某些其他原因而不忙,它将看到
setTimeout
排队的任务,并运行该函数,记录这两个语句。 - 在任何时候,如果有人点击了正文,浏览器会将任务发布到事件循环以运行点击处理函数。事件循环,因为它不断检查要做什么,将看到这一点,并运行该功能。
你可以看到在此示例中,如何在 JavaScript 代码中有几种不同类型的入口点,事件循环调用它们:
<script>
元素立即被调用setTimeout
任务将发布到事件循环并运行一次- 点击处理程序任务可以多次发布并每次运行
事件循环的每一轮都有很多东西; 只有部分人会调用这些 JavaScript 任务。有关完整详细信息,请参阅 HTML 规范
最后一件事:我们说每个事件循环任务运行完成是什么意思?我们的意思是通常不可能中断排队等待作为任务运行的代码块,并且永远不可能运行与另一个代码块交错的代码。例如,即使你在完美时间点击,也无法获得上述代码来记录两个 setTimeout callback log 1/2"
之间的 onclick
。这是由于任务发布的工作方式; 它是合作的和基于队列的,而不是先发制人的。