搜尋
首頁CMS教程&#&按解讀JavaScript中的事件循環

解讀JavaScript中的事件循環

Sep 03, 2023 pm 01:17 PM
會放入隊尾等待javascript引擎執行。透過事件隊列

解讀JavaScript中的事件循環

您可能已經知道 JavaScript 是單執行緒程式語言。這意味著 JavaScript 在 Web 瀏覽器或 Node.js 中的單一主執行緒上運行。在單一主執行緒上運行意味著一次只運行一段 JavaScript 程式碼。

JavaScript 中的事件循環在決定程式碼如何在主執行緒上執行方面發揮著重要作用。事件循環負責一些事情,例如程式碼的執行以及事件的收集和處理。它也處理任何排隊子任務的執行。

在本教程中,您將學習 JavaScript 中事件循環的基礎知識。

事件循環如何運作

為了理解事件循環的工作原理,您需要了解三個重要術語。

堆疊

呼叫堆疊只是追蹤函數執行上下文的函數呼叫堆疊。該堆疊遵循後進先出 (LIFO) 原則,這意味著最近調用的函數將是第一個執行的函數。

隊列

佇列包含一系列由 JavaScript 執行的任務。該佇列中的任務可能會導致呼叫函數,然後將其放入堆疊中。僅當堆疊為空時才開始佇列的處理。隊列中的項目遵循先進先出 (FIFO) 原則。這意味著最舊的任務將首先完成。

堆基本上是儲存和分配物件的一大塊記憶體區域。它的主要目的是儲存堆疊中的函數可能使用的資料。

基本上,JavaScript 是單執行緒的,一次執行一個函數。這個單一函數被放置在堆疊上。該函數還可以包含其他巢狀函數,這些函數將放置在堆疊中的上方。堆疊遵循 LIFO 原則,因此最近呼叫的巢狀函數將首先執行。

API 請求或計時器等非同步任務將會新增至佇列以便稍後執行。 JavaScript 引擎在空閒時開始執行佇列中的任務。

考慮以下範例:

function helloWorld() {
    console.log("Hello, World!");
}

function helloPerson(name) {
    console.log(`Hello, ${name}!`);
}

function helloTeam() {
    console.log("Hello, Team!");
    helloPerson("Monty");
}

function byeWorld() {
    console.log("Bye, World!");
}

helloWorld();
helloTeam();
byeWorld();

/* Outputs:

Hello, World!
Hello, Team!
Hello, Monty!
Bye, World!

*/

讓我們看看如果運行上面的程式碼,堆疊和佇列會是什麼樣子。

呼叫 helloWorld() 函數並將其放入堆疊中。它記錄 Hello, World! 完成其執行,因此它被從堆疊中取出。接下來呼叫 helloTeam() 函數並將其放入堆疊中。在執行過程中,我們記錄 Hello, Team! 並呼叫 helloPerson()helloTeam() 的執行還沒完成,所以它停留在堆疊上,而 helloPerson() 則放在它上面。

後進先出原則規定 helloPerson() 現在執行。這會將 Hello, Monty! 記錄到控制台,從而完成其執行,並且 helloPerson() 將從堆疊中取出。之後 helloTeam() 函數就會出棧,我們最後到達 byeWorld()。它會記錄再見,世界! ,然後從堆疊中消失。

隊列一直是空的。

現在,考慮上述程式碼的細微變化:

function helloWorld() {
    console.log("Hello, World!");
}

function helloPerson(name) {
    console.log(`Hello, ${name}!`);
}

function helloTeam() {
    console.log("Hello, Team!");
    setTimeout(() => {
        helloPerson("Monty");
    }, 0);
}

function byeWorld() {
    console.log("Bye, World!");
}

helloWorld();
helloTeam();
byeWorld();

/* Outputs:

Hello, World!
Hello, Team!
Bye, World!
Hello, Monty!

*/

我們在這裡所做的唯一更改是使用 setTimeout()。但是,超時已設定為零。因此,我們期望 Hello, Monty!Bye, World! 之前輸出。如果您了解事件循環的工作原理,您就會明白為什麼不會發生這種情況。

helloTeam()入堆疊時,遇到setTimeout()方法。但是,setTimeout() 中對 helloPerson() 的呼叫會被放入佇列中,一旦沒有同步任務需要執行,就會被執行。

一旦對 byeWorld() 的呼叫完成,事件循環將檢查佇列中是否有任何掛起的任務,並找到對 helloPerson() 的呼叫。此時,它執行該函數並將 Hello, Monty! 記錄到控制台。

這表示您提供給 setTimeout() 的超時持續時間並不是回呼執行的保證時間。這是執行回調的最短時間。

保持我們的網頁回應

JavaScript 的一個有趣的功能是它會執行一個函數直到完成。這意味著只要函數在堆疊上,事件循環就無法處理佇列中的任何其他任務或執行其他函數。

這可能會導致網頁“掛起”,因為它無法執行其他操作,例如處理使用者輸入或進行與 DOM 相關的更改。考慮以下範例,我們在其中查找給定範圍內的素數數量:

function isPrime(num) {
  if (num <= 1) {
    return false;
  }

  for (let i = 2; i <= Math.sqrt(num); i++) {
    if (num % i === 0) {
      return false;
    }
  }
  
  return true;
}

function listPrimesInRange(start, end) {
  const primes = [];

  for (let num = start; num <= end; num++) {
    if (isPrime(num)) {
      primes.push(num);
    }
  }

  return primes;
}

在我們的 listPrimesInRange() 函數中,我們迭代從 startend 的數字。對於每個數字,我們呼叫 isPrime() 函數來查看它是否是質數。 isPrime() 函數本身有一個for 循環,從2Math.sqrt(num) 來決定數字是否為素數。

查找给定范围内的所有素数可能需要一段时间,具体取决于您使用的值。当浏览器进行此计算时,它无法执行任何其他操作。这是因为 listPrimesInRange() 函数将保留在堆栈中,浏览器将无法执行队列中的任何其他任务。

现在,看一下以下函数:

function listPrimesInRangeResponsively(start) {
  let next = start + 100,000;

  if (next > end) {
    next = end;
  }

  for (let num = start; num <= next; num++) {
    if (isPrime(num)) {
      primeNumbers.push(num);
    }

    if (num == next) {
      percentage = ((num - begin) * 100) / (end - begin);
      percentage = Math.floor(percentage);

      progress.innerText = `Progress ${percentage}%`;

      if (num != end) {
        setTimeout(() => {
          listPrimesInRangeResponsively(next + 1);
        });
      }
    }

    if (num == end) {
      percentage = ((num - begin) * 100) / (end - begin);
      percentage = Math.floor(percentage);

      progress.innerText = `Progress ${percentage}%`;

      heading.innerText = `${primeNumbers.length - 1} Primes Found!`;

      console.log(primeNumbers);

      return primeNumbers;
    }
  }
}

这一次,我们的函数仅在批量处理范围时尝试查找素数。它通过遍历所有数字但一次仅处理其中的 100,000 个来实现这一点。之后,它使用 setTimeout() 触发对同一函数的下一次调用。

setTimeout() 被调用而没有指定延迟时,它会立即将回调函数添加到事件队列中。

下一个调用将被放入队列中,暂时清空堆栈以处理任何其他任务。之后,JavaScript 引擎开始在下一批 100,000 个数字中查找素数。

尝试单击此页面上的计算(卡住)按钮,您可能会收到一条消息,指出该网页正在减慢您的浏览器速度,并建议您停止该脚本。 p>

另一方面,单击计算(响应式)按钮仍将使网页保持响应式。

最终想法

在本教程中,我们了解了 JavaScript 中的事件循环以及它如何有效地执行同步和异步代码。事件循环使用队列来跟踪它必须执行的任务。

由于 JavaScript 不断执行函数直至完成,因此进行大量计算有时会“挂起”浏览器窗口。根据我们对事件循环的理解,我们可以重写我们的函数,以便它们批量进行计算。这允许浏览器保持窗口对用户的响应。它还使我们能够定期向用户更新我们在计算中取得的进展。

以上是解讀JavaScript中的事件循環的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何輕鬆地將博客從 WordPress.com 移至 WordPress.org如何輕鬆地將博客從 WordPress.com 移至 WordPress.orgApr 18, 2025 am 11:33 AM

您想將博客從 WordPress.com 移至 WordPress.org 嗎? 許多初學者從 WordPress.com 開始,但很快意識到其局限性,並希望切換到自託管 WordPress.org 平台。 在本分步指南中,我們將向您展示如何正確地將博客從 WordPress.com 移動到 WordPress.org。 為什麼從 WordPress.com 遷移到 WordPress.org? WordPress.com 允許任何人通過創建帳戶來

如何使用 IFTTT 自動化 WordPress 和社交媒體(及更多)如何使用 IFTTT 自動化 WordPress 和社交媒體(及更多)Apr 18, 2025 am 11:27 AM

您是否正在尋找自動化 WordPress 網站和社交媒體帳戶的方法? 通過自動化,您將能夠在 Facebook、Twitter、LinkedIn、Instagram 等平台上自動分享您的 WordPress 博客文章或更新。 在本文中,我們將向您展示如何使用 IFTTT、Zapier 和 Uncanny Automator 輕鬆實現 WordPress 和社交媒體的自動化。 為什麼要自動化 WordPress 和社交媒體? 自動化您的WordPre

如何修復 WordPress 中的自定義菜單項限制如何修復 WordPress 中的自定義菜單項限制Apr 18, 2025 am 11:18 AM

就在幾天前,我們的一位用戶報告了一個不尋常的問題。問題是他達到了自定義菜單項的限制。達到菜單項限制後他保存的任何內容都將根本無法保存。我們從未聽說過這個問題,因此我們決定在本地安裝上嘗試一下。創建了 200 多個菜單項並保存。效果很好。將 100 個項目移至下拉列表中,保存效果非常好。那時我們就知道這與服務器有關。經過進一步研究,似乎還有許多其他人也遇到了同樣的問題。深入挖掘後,我們發現了一張 trac 票證 ( #14134 ) 強調了這個問題。在閱讀了非常

如何在 WordPress 中將自定義元字段添加到自定義分類法如何在 WordPress 中將自定義元字段添加到自定義分類法Apr 18, 2025 am 11:11 AM

您需要將自定義元字段添加到 WordPress 中的自定義分類法嗎? 自定義分類法可讓您組織除類別和標籤之外的內容。有時添加其他字段來描述它們很有用。 在本文中,我們將向您展示如何將其他元字段添加到他們創建的分類法中。 何時應將自定義元字段添加到自定義分類法? 當您在WordPress 網站上創建新內容時,您可以使用兩種默認分類法(類別和標籤)對其進行組織。 一些網站受益於自定義分類法的使用。這些允許您以其他方式對內容進行排序。 例如,

如何使用 Windows Live Writer 遠程發佈到 WordPress如何使用 Windows Live Writer 遠程發佈到 WordPressApr 18, 2025 am 11:02 AM

Windows live writer 是一款多功能工具,可讓您直接從桌面將帖子發佈到 WordPress 博客上。這意味著您根本不需要登錄 WordPress 管理面板來更新您的博客。在本教程中,我將向您展示如何使用 Windows Live Writer 為您的 WordPress 博客啟用桌面發布。 如何在 WordPress 上設置 Windows Live Writer 第 1 步: 要通過 Windows Live Writer 在 WordPr

如何修復 WordPress 可視化編輯器中的白色文本和缺失按鈕如何修復 WordPress 可視化編輯器中的白色文本和缺失按鈕Apr 18, 2025 am 10:52 AM

最近,我們的一位用戶報告了一個非常奇怪的安裝問題。寫帖子時,他們看不到自己寫的任何內容。因為帖子編輯器的文字是白色的。更重要的是,所有可視化編輯器按鈕都丟失了,並且從可視化切換到 HTML 的功能也不起作用。在本文中,我們將向您展示如何修復 WordPress 可視化編輯器中的白色文本和缺失按鈕問題。 初學者註意事項:如果您正在尋找可能在其他網站的屏幕截圖中看到的隱藏按鈕,那麼您可能正在尋找廚房水槽。您必須單擊廚房水槽圖標才能看到其他選項,例如下劃線、從單詞複製等。

如何在 WordPress 中顯示用戶電子郵件中的頭像如何在 WordPress 中顯示用戶電子郵件中的頭像Apr 18, 2025 am 10:51 AM

您想在 WordPress 中顯示用戶電子郵件中的頭像嗎? Gravatar 是一項將用戶的電子郵件地址連接到在線頭像的網絡服務。 WordPress 會自動在評論部分顯示訪問者的頭像,但您可能也想將它們添加到網站的其他區域。 在本文中,我們將向您展示如何在 WordPress 中顯示用戶電子郵件中的頭像。 什麼是 Gravatar 以及為什麼要顯示它? Gravatar代表全球認可的頭像,它允許人們將圖片鏈接到他們的電子郵件地址。 如果網站支

如何更改 WordPress 中的默認媒體上傳位置如何更改 WordPress 中的默認媒體上傳位置Apr 18, 2025 am 10:47 AM

您想更改 WordPress 中的默認媒體上傳位置嗎? 將媒體文件移動到其他文件夾可以提高網站的速度和性能,並幫助您更快地創建備份。它還使您可以自由地以最適合您的方式組織文件。 在本文中,我們將向您展示如何更改 WordPress 中的默認媒體上傳位置。 為什麼要更改默認媒體上傳位置? 默認情況下,WordPress 將所有圖像和其他媒體文件存儲在 /wp-content/uploads/ 文件夾中。 在此文件夾中,您將找到不同年份和月份的子

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。