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 瀏覽器。

  1. HTML 解析器將首先執行 <script>。它將執行完成。
  2. setTimeout 的呼叫告訴瀏覽器,在 100 毫秒之後,它應該將任務排隊以執行給定的操作。
  3. 與此同時,事件迴圈負責不斷檢查是否還有其他事情要做:例如,渲染網頁。
  4. 在 100 毫秒之後,如果事件迴圈由於某些其他原因而不忙,它將看到 setTimeout 排隊的任務,並執行該函式,記錄這兩個語句。
  5. 在任何時候,如果有人點選了正文,瀏覽器會將任務釋出到事件迴圈以執行點選處理函式。事件迴圈,因為它不斷檢查要做什麼,將看到這一點,並執行該功能。

你可以看到在此示例中,如何在 JavaScript 程式碼中有幾種不同型別的入口點,事件迴圈呼叫它們:

  • <script> 元素立即被呼叫
  • setTimeout 任務將釋出到事件迴圈並執行一次
  • 點選處理程式任務可以多次釋出並每次執行

事件迴圈的每一輪都有很多東西; 只有部分人會呼叫這些 JavaScript 任務。有關完整詳細資訊,請參閱 HTML 規範

最後一件事:我們說每個事件迴圈任務執行完成是什麼意思?我們的意思是通常不可能中斷排隊等待作為任務執行的程式碼塊,並且永遠不可能執行與另一個程式碼塊交錯的程式碼。例如,即使你在完美時間點選,也無法獲得上述程式碼來記錄兩個 setTimeout callback log 1/2" 之間的 onclick。這是由於任務釋出的工作方式; 它是合作的和基於佇列的,而不是先發制人的。