狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

JavaScript中的事件循環(huán)機制

admin
2024年11月3日 7:9 本文熱度 404

引言

事件循環(huán)機制是 JavaScript 處理異步操作的核心,它確保代碼的執(zhí)行順序與預期順序一致。JavaScript 是一種單線程語言,這意味著它一次只能執(zhí)行一個任務(wù)。這可能會導致一個嚴重的問題:如果一個線程被阻塞,整個程序?qū)⒆兊脽o響應(yīng)。為了解決這個問題,JavaScript 引入了事件循環(huán)機制。該機制允許 JavaScript 在執(zhí)行任務(wù)的同時處理異步操作,從而提高程序性能并確保代碼執(zhí)行順序與預期順序匹配。

循環(huán)的本質(zhì)

事件循環(huán)機制中的“循環(huán)”代表其重復過程,一直持續(xù)到?jīng)]有更多任務(wù)需要處理為止。

異步編程的基礎(chǔ)

事件循環(huán)機制是 JavaScript 異步編程的基礎(chǔ)。像 Promises、Generators 和 Async/Await 這些概念都是基于事件循環(huán)機制的。

基本理論

事件循環(huán)機制的基本原理

事件循環(huán)機制的基本原理是 JavaScript 維護一個執(zhí)行棧和一個任務(wù)隊列。在執(zhí)行任務(wù)時,JavaScript 將它們放入執(zhí)行棧中。JavaScript 任務(wù)分為同步任務(wù)和異步任務(wù)。同步任務(wù)直接在執(zhí)行棧中執(zhí)行,而異步任務(wù)則被放入任務(wù)隊列中等待執(zhí)行。當執(zhí)行棧中的所有任務(wù)完成后,JavaScript 引擎從任務(wù)隊列中讀取一個任務(wù)并將其放入執(zhí)行棧中執(zhí)行。這個過程不斷重復,直到任務(wù)隊列為空,標志著事件循環(huán)機制的結(jié)束。

用 setTimeout/setInterval 和 XHR/fetch 舉例

讓我們用 setTimeout/setInterval(定時任務(wù))和 XHR/fetch(網(wǎng)絡(luò)請求)的例子來說明這個概念。

當執(zhí)行 setTimeout/setInterval 和 XHR/fetch 時,這些是帶有異步回調(diào)函數(shù)的同步任務(wù):

  • setTimeout/setInterval:當遇到 setTimeout/setInterval 時,JavaScript 引擎通知定時器觸發(fā)線程有一個定時任務(wù)要執(zhí)行,然后繼續(xù)執(zhí)行后續(xù)的同步任務(wù)。定時器觸發(fā)線程等待指定的時間,然后將回調(diào)函數(shù)放入任務(wù)隊列中執(zhí)行。
  • XHR/fetch:當遇到 XHR/fetch 時,JavaScript 引擎通知異步 HTTP 請求線程有一個網(wǎng)絡(luò)請求要發(fā)送,然后繼續(xù)執(zhí)行后續(xù)的同步任務(wù)。異步 HTTP 請求線程等待網(wǎng)絡(luò)請求響應(yīng)。成功后,它將回調(diào)函數(shù)放入任務(wù)隊列中執(zhí)行。

完成同步任務(wù)后,JavaScript 引擎向事件觸發(fā)線程檢查是否有任何待處理的回調(diào)函數(shù)。如果有,它將回調(diào)函數(shù)放入執(zhí)行棧中執(zhí)行。如果沒有,JavaScript 引擎保持空閑,等待新任務(wù)。這種異步和同步任務(wù)的交錯執(zhí)行實現(xiàn)了高效的任務(wù)管理。

宏任務(wù)和微任務(wù)

宏任務(wù)和微任務(wù)的概念

宏任務(wù)和微任務(wù)是事件循環(huán)機制中的兩個關(guān)鍵概念。

  • 宏任務(wù):包括 setTimeout、setInterval、I/O 操作和 UI 渲染等任務(wù)。
  • 微任務(wù):包括 Promise 回調(diào)、MutationObserver 回調(diào)和 process.nextTick 等任務(wù)。

宏任務(wù)和微任務(wù)的執(zhí)行順序

  • 宏任務(wù):宏任務(wù)在事件循環(huán)的每次迭代中按順序執(zhí)行。在每次迭代中,從宏任務(wù)隊列中取出一個宏任務(wù)并執(zhí)行。
  • 微任務(wù):微任務(wù)在當前宏任務(wù)完成后且在下一個宏任務(wù)開始前立即執(zhí)行。事件循環(huán)將持續(xù)執(zhí)行微任務(wù)隊列中的所有微任務(wù),直到隊列為空,然后再繼續(xù)執(zhí)行下一個宏任務(wù)。

這確保了微任務(wù)獲得更高的優(yōu)先級,并在下一個宏任務(wù)開始之前完成,從而能夠更高效地處理任務(wù),并在異步操作中獲得更好的性能。

實用技巧

通過示例熟悉事件循環(huán)機制

  • 示例 1
console.log('Start');

setTimeout(() => {
  console.log('setTimeout Callback');
}, 0);

Promise.resolve().then(() => {
  console.log('Promise then');
});

console.log('End');

分析:

  • 首先執(zhí)行同步代碼,打印“Start”。
  • 遇到 setTimeout,它是一個宏任務(wù),所以將其放入宏任務(wù)隊列稍后執(zhí)行。
  • 遇到 Promise.resolve().then,它是一個微任務(wù),所以將其放入微任務(wù)隊列,在當前同步代碼完成后執(zhí)行。
  • 繼續(xù)執(zhí)行同步代碼,打印“End”。
  • 現(xiàn)在檢查微任務(wù)隊列,有一個微任務(wù)(Promise.then),所以執(zhí)行它,打印“Promise then”。
  • 最后檢查宏任務(wù)隊列,有一個宏任務(wù)(setTimeout 回調(diào)),所以執(zhí)行它,打印“setTimeout Callback”。

輸出:

Start
End
Promise then
setTimeout Callback
  • 示例 2
console.log('Start');

new Promise((resolve) => {
  console.log('Promise Executor');
  resolve();
}).then(() => {
  console.log('Promise then');
});

console.log('End');

分析:

  • 首先執(zhí)行同步代碼,打印“Start”。
  • 遇到 Promise 構(gòu)造函數(shù),其內(nèi)部的執(zhí)行器函數(shù)立即運行(作為當前宏任務(wù)的一部分),打印“Promise Executor”。
  • then 方法安排一個微任務(wù),它將在所有同步代碼完成后運行。
  • 繼續(xù)執(zhí)行同步代碼,打印“End”。
  • 現(xiàn)在檢查微任務(wù)隊列,有一個微任務(wù)(Promise.then),所以執(zhí)行它,打印“Promise then”。

輸出:

Start
Promise Executor
End
Promise then
  • 示例 3
console.log('Start');

async function asyncFunction({
  await new Promise((resolve) => {
    console.log('Promise');
    setTimeout(resolve, 0);
  });
  console.log('asyncawait');
}

asyncFunction();

console.log('End');

分析:

  • 同步代碼執(zhí)行:首先打印“Start”,因為這是遇到的第一個同步代碼。
  • 進入 asyncFunction:接著執(zhí)行 asyncFunction。在 asyncFunction 內(nèi)部,打印“Promise”,因為 Promise 構(gòu)造函數(shù)的同步部分立即運行。
  • 遇到 await:當執(zhí)行到 await new Promise(...) 時,asyncFunction 在這里暫停,等待 Promise 被解決。
  • 繼續(xù)執(zhí)行全局腳本:在等待 await 時,控制權(quán)返回給調(diào)用者,所以執(zhí)行 console.log('End'),打印“End”。
  • 事件循環(huán)和宏任務(wù):當遇到延遲為 0 毫秒的 setTimeout 時,其回調(diào)函數(shù)(即 resolve)被放入宏任務(wù)隊列。一旦當前執(zhí)行棧為空且微任務(wù)隊列被處理,事件循環(huán)檢查宏任務(wù)隊列并執(zhí)行 setTimeout 回調(diào),解決 Promise。
  • Promise 解決后的微任務(wù):Promise 解決后,await 后面的代碼(即 console.log('asyncawait'))被放入微任務(wù)隊列。在下一次事件循環(huán)迭代中,處理微任務(wù)隊列,打印“asyncawait”。

輸出:

Start
Promise
End
asyncawait

通過分析這些示例,你應(yīng)該對事件循環(huán)機制有了扎實的理解。

性能優(yōu)化:利用事件循環(huán)機制

  1. 減少 UI 阻塞:將耗時操作放在微任務(wù)或宏任務(wù)隊列的末尾,以確保 UI 線程能夠及時響應(yīng)用戶交互。例如,使用 requestAnimationFrame 進行動畫渲染,以與瀏覽器的繪制周期同步,減少頁面重繪開銷。
  2. 拆分長任務(wù):如果一個任務(wù)花費時間過長,考慮將其拆分為較小的任務(wù),并在其間插入其他任務(wù),如 UI 更新。這種方法有助于保持應(yīng)用程序的響應(yīng)性。例如,將大數(shù)據(jù)處理分成多個塊,并在每個塊之后讓出控制權(quán)。
  3. 優(yōu)先使用 Promise 和 async/await:與傳統(tǒng)回調(diào)相比,Promise 和 async/await 提供了更清晰的代碼結(jié)構(gòu)和更好的錯誤處理。它們還能更有效地管理事件循環(huán),使異步代碼看起來更像同步代碼,更易于理解和維護。
  4. 避免過度使用微任務(wù):雖然微任務(wù)具有高優(yōu)先級,但過度依賴它們可能導致微任務(wù)隊列堆積。特別是在遞歸調(diào)用或復雜邏輯中,可能會無意中造成性能瓶頸。平衡宏任務(wù)和微任務(wù)的使用,以優(yōu)化執(zhí)行效率和響應(yīng)性。
  5. 利用 nextTick:在 Vue.js 中,nextTick 用于在 Vue 的異步 DOM 更新隊列清除后執(zhí)行某些操作。Vue.js 使用異步 DOM 更新來提高性能,這意味著數(shù)據(jù)更改不會立即更新視圖。相反,更新在同步代碼執(zhí)行完成后批量進行,減少 DOM 操作并提高性能。nextTick 方法依賴于 JavaScript 的事件循環(huán)機制。

深入探究

Node.js 事件循環(huán)模型

要深入了解 Node.js 事件循環(huán)模型,請參閱官方 Node.js 文檔。以下是一個簡要概述:

Node.js 事件循環(huán)分為六個階段,每個階段都有一個用于宏任務(wù)的先進先出隊列和一個用于微任務(wù)的先進先出隊列。在每個階段之后,循環(huán)檢查微任務(wù)隊列并處理它,直到隊列為空,然后再進入下一個階段。

每個階段處理特定任務(wù):

  • 定時器:執(zhí)行 setTimeout 和 setInterval 的回調(diào)函數(shù)。
  • I/O 回調(diào):執(zhí)行已完成 I/O 操作的回調(diào)函數(shù)(不包括關(guān)閉、定時器和 setImmediate 的回調(diào)函數(shù))。
  • 空閑、準備:由 Node.js 內(nèi)部使用,通常與用戶代碼無關(guān)。
  • 輪詢:獲取新的 I/O 事件;在適當?shù)臅r候,Node.js 會在這里阻塞。
  • 檢查:執(zhí)行 setImmediate 回調(diào)函數(shù)。
  • 關(guān)閉回調(diào):執(zhí)行關(guān)閉事件回調(diào)函數(shù)。

這個模型確保了 Node.js 中事件驅(qū)動、異步編程范式的高效運行。

瀏覽器事件循環(huán)模型

瀏覽器中的事件循環(huán)模型如前面示例所述進行操作。它通過平衡同步任務(wù)、宏任務(wù)和微任務(wù)來維護執(zhí)行順序。

邊界情況分析

  1. 微任務(wù)嵌套:微任務(wù)可以嵌套,這意味著一個微任務(wù)可以向隊列中添加更多微任務(wù)。這可能導致微任務(wù)堆積,可能會使事件循環(huán)“餓死”宏任務(wù),延遲它們的執(zhí)行。
  2. 宏任務(wù)嵌套:直接的宏任務(wù)嵌套(例如,在 setTimeout 回調(diào)中調(diào)用另一個 setTimeout)不會改變執(zhí)行順序,但可能會影響事件循環(huán)的流暢性,特別是如果它們涉及 I/O 操作或密集計算。
  3. 定時器的不準確性:像 setTimeout 和 setInterval 這樣的定時器保證在至少指定的時間后執(zhí)行,但可能會因為以下原因而延遲執(zhí)行:
  • 當前執(zhí)行棧不為空。
  • 宏任務(wù)隊列中有待處理的任務(wù)。
  • 系統(tǒng)資源限制或高 CPU 使用率。

盡管這些環(huán)境在細節(jié)上有所不同,但它們都遵循宏任務(wù)和微任務(wù)分離的原則。

理解 nextTick

在 Vue.js 中,nextTick 是一個方法,用于在 Vue 的異步 DOM 更新隊列清除后執(zhí)行回調(diào)函數(shù)。Vue.js 使用異步 DOM 更新來提高性能,這意味著數(shù)據(jù)更改不會立即更新視圖。相反,更新在同步代碼執(zhí)行完成后批量進行,減少 DOM 操作并提高性能。nextTick 方法依賴于 JavaScript 的事件循環(huán)機制。

nextTick 的使用場景:

  1. 獲取更新后的 DOM 元素:確保在 nextTick 回調(diào)函數(shù)中獲取最新更新的 DOM 元素。
  2. 避免不必要的渲染:組合多個數(shù)據(jù)修改并使用 nextTick 確保 DOM 元素只更新一次,減少渲染次數(shù)并提高性能。

結(jié)論

通過有效地理解和利用事件循環(huán)機制,你可以顯著提高 JavaScript 應(yīng)用程序的性能和響應(yīng)性。平衡宏任務(wù)和微任務(wù)的使用、避免過度嵌套以及利用 async/await 可以使代碼更易于維護和高效。


該文章在 2024/11/4 10:43:07 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved