搜尋
首頁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開發的5個最佳ID(以及原因)WordPress開發的5個最佳ID(以及原因)Mar 03, 2025 am 10:53 AM

我為WordPress開發選擇了正確的綜合開發環境(IDE)十年後,我探索了WordPress開發的眾多集成開發環境(IDE)。 純粹的品種 - 從免費到商業,基本到FEA

使用OOP技術創建WordPress插件使用OOP技術創建WordPress插件Mar 06, 2025 am 10:30 AM

本教程演示了使用面向對象的編程(OOP)原理構建WordPress插件,利用Dribbble API。 讓我們在保留原始含義和結構的同時完善文本以清晰和簡潔。 object-ori

如何將PHP數據和字符串傳遞給WordPress中的JavaScript如何將PHP數據和字符串傳遞給WordPress中的JavaScriptMar 07, 2025 am 09:28 AM

將PHP數據傳遞給JavaScript的最佳實踐:WP_LOCALIZE_SCRIPT和WP_ADD_INLINE_SCRIPT的比較是PHP文件中靜態字符串中數據存儲數據的最佳實踐。 如果在您的JavaScript代碼中需要此數據,請合併

如何使用WordPress插件嵌入和保護PDF文件如何使用WordPress插件嵌入和保護PDF文件Mar 09, 2025 am 11:08 AM

本指南演示瞭如何使用WordPress PDF插件在WordPress帖子和頁面中嵌入和保護PDF文件。 PDFS為從目錄到演示文稿提供了一種用戶友好的,普遍訪問的格式。 此方法ENS

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 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

mPDF

mPDF

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

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具