日韩欧美国产精品免费一二-日韩欧美国产精品亚洲二区-日韩欧美国产精品专区-日韩欧美国产另-日韩欧美国产免费看-日韩欧美国产免费看清风阁

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

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

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

引言

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

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

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

異步編程的基礎(chǔ)

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

基本理論

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

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

用 setTimeout/setInterval 和 XHR/fetch 舉例

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

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

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

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

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

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

宏任務(wù)和微任務(wù)是事件循環(huán)機(jī)制中的兩個(gè)關(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ù)隊(duì)列中取出一個(gè)宏任務(wù)并執(zhí)行。
  • 微任務(wù):微任務(wù)在當(dāng)前宏任務(wù)完成后且在下一個(gè)宏任務(wù)開始前立即執(zhí)行。事件循環(huán)將持續(xù)執(zhí)行微任務(wù)隊(duì)列中的所有微任務(wù),直到隊(duì)列為空,然后再繼續(xù)執(zhí)行下一個(gè)宏任務(wù)。

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

實(shí)用技巧

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

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

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

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

console.log('End');

分析:

  • 首先執(zhí)行同步代碼,打印“Start”。
  • 遇到 setTimeout,它是一個(gè)宏任務(wù),所以將其放入宏任務(wù)隊(duì)列稍后執(zhí)行。
  • 遇到 Promise.resolve().then,它是一個(gè)微任務(wù),所以將其放入微任務(wù)隊(duì)列,在當(dāng)前同步代碼完成后執(zhí)行。
  • 繼續(xù)執(zhí)行同步代碼,打印“End”。
  • 現(xiàn)在檢查微任務(wù)隊(duì)列,有一個(gè)微任務(wù)(Promise.then),所以執(zhí)行它,打印“Promise then”。
  • 最后檢查宏任務(wù)隊(duì)列,有一個(gè)宏任務(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ù)立即運(yùn)行(作為當(dāng)前宏任務(wù)的一部分),打印“Promise Executor”。
  • then 方法安排一個(gè)微任務(wù),它將在所有同步代碼完成后運(yùn)行。
  • 繼續(xù)執(zhí)行同步代碼,打印“End”。
  • 現(xiàn)在檢查微任務(wù)隊(duì)列,有一個(gè)微任務(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”,因?yàn)檫@是遇到的第一個(gè)同步代碼。
  • 進(jìn)入 asyncFunction:接著執(zhí)行 asyncFunction。在 asyncFunction 內(nèi)部,打印“Promise”,因?yàn)?Promise 構(gòu)造函數(shù)的同步部分立即運(yùn)行。
  • 遇到 await:當(dāng)執(zhí)行到 await new Promise(...) 時(shí),asyncFunction 在這里暫停,等待 Promise 被解決。
  • 繼續(xù)執(zhí)行全局腳本:在等待 await 時(shí),控制權(quán)返回給調(diào)用者,所以執(zhí)行 console.log('End'),打印“End”。
  • 事件循環(huán)和宏任務(wù):當(dāng)遇到延遲為 0 毫秒的 setTimeout 時(shí),其回調(diào)函數(shù)(即 resolve)被放入宏任務(wù)隊(duì)列。一旦當(dāng)前執(zhí)行棧為空且微任務(wù)隊(duì)列被處理,事件循環(huán)檢查宏任務(wù)隊(duì)列并執(zhí)行 setTimeout 回調(diào),解決 Promise。
  • Promise 解決后的微任務(wù):Promise 解決后,await 后面的代碼(即 console.log('asyncawait'))被放入微任務(wù)隊(duì)列。在下一次事件循環(huán)迭代中,處理微任務(wù)隊(duì)列,打印“asyncawait”。

輸出:

Start
Promise
End
asyncawait

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

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

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

深入探究

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

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

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

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

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

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

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

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

邊界情況分析

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

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

理解 nextTick

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

nextTick 的使用場景:

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

結(jié)論

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


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

主站蜘蛛池模板: 国语精品91自产拍在线观看二区 | 亚洲影院 | 日本欧美大码 | 久99精| 国产午夜亚洲精品不卡电影 | 成人免费视频一区二区 | 影音先锋2025色资源网 | 两个人看的视频在线观看 | 肉大捧一进一出免费视频 | 亚洲精品一级高清在线播放国 | 一区二区欧美 | 日本三级网站在线观看视频 | 影院手机电影在线 | 2025中文日产幕无线 | 亚洲高清在线 | 伊人影视 | 妺妺窝人体色www看人体 | 久产久精九国品在线 | 国产在线观看免费人成视频 | 国色天香精 | 国产精品美 | 免费无毒a网站在线观看 | 一国产一国产 | 国产精品丝袜黑色高跟鞋 | 亚洲国产欧洲在线一区 | 日本不卡 | 超97在线观看视频 | 国产美女爽到喷出水来视频 | 久青青视频在线观看久 | 亚洲欧美日韩在线一区二区三区 | 91精品国产免 | 中文字幕va一区二 | 日韩欧美一区二区三区在线观看 | 一区二区本码 | 视频一区 | 成年免费国产大片 | 亚洲一区二区三区高清 | 国产激情电影综合在线看 | 亚洲精品在线视频 | 精品伦精品一区二区三区视 | 电视剧大全免费全集观看 |