JS中的事件循環(huán)是什么?如何理解?

事件循環(huán)JavaScript處理異步操作的核心機(jī)制,其關(guān)鍵在于宏任務(wù)與微任務(wù)的執(zhí)行順序。javascript是單線程語言,通過事件循環(huán)管理代碼執(zhí)行順序;當(dāng)調(diào)用為空時(shí),事件循環(huán)會從任務(wù)隊(duì)列中取出任務(wù)執(zhí)行。事件分為宏任務(wù)(如settimeout、i/o操作)和微任務(wù)(如promise.then、mutationobserver)。事件循環(huán)流程為:1.執(zhí)行一個(gè)宏任務(wù);2.清空所有當(dāng)前可用微任務(wù);3.渲染頁面(如需);4.執(zhí)行下一個(gè)宏任務(wù)。例如,即使settimeout設(shè)為0毫秒,promise.then仍會在settimeout之前執(zhí)行,因其屬于微任務(wù)。理解事件循環(huán)有助于優(yōu)化異步邏輯安排,避免阻塞主線程或造成瀏覽器“饑餓”。實(shí)際開發(fā)中,若需延遲執(zhí)行可用settimeout(fn, 0),若需盡快執(zhí)行可用promise.then。可通過瀏覽器開發(fā)者工具打斷點(diǎn)或控制臺組合異步任務(wù)觀察事件循環(huán)行為,從而加深理解。

JS中的事件循環(huán)是什么?如何理解?

事件循環(huán)是 JavaScript 中處理異步操作的核心機(jī)制,它決定了代碼的執(zhí)行順序,尤其是當(dāng)有定時(shí)器、Promise、回調(diào)函數(shù)等異步任務(wù)時(shí)。理解事件循環(huán),能幫助我們避免一些看似“奇怪”的執(zhí)行順序問題。


什么是事件循環(huán)?

JavaScript 最初是單線程語言,意味著同一時(shí)間只能做一件事。為了處理異步任務(wù)(比如點(diǎn)擊事件、網(wǎng)絡(luò)請求),JS 引入了事件循環(huán)機(jī)制。

簡單來說,事件循環(huán)就是一個(gè)不斷運(yùn)行的循環(huán),檢查調(diào)用棧是否為空,如果空了,就從任務(wù)隊(duì)列中取出一個(gè)任務(wù)推入調(diào)用棧執(zhí)行。這個(gè)過程持續(xù)進(jìn)行,直到所有任務(wù)完成。

舉個(gè)例子:

console.log("Start");  setTimeout(() => {   console.log("Timeout"); }, 0);  Promise.resolve().then(() => {   console.log("Promise"); });  console.log("End");

輸出順序是:

Start End Promise Timeout

雖然 setTimeout 設(shè)置為 0 毫秒,但 Promise 的 .then 會優(yōu)先于 setTimeout 執(zhí)行。這就是事件循環(huán)在背后起作用的結(jié)果。


宏任務(wù)與微任務(wù)的區(qū)別

事件循環(huán)中的任務(wù)分為兩類:宏任務(wù)(macrotask)和微任務(wù)(microtask)。

  • 宏任務(wù)包括:setTimeout、setInterval、I/O 操作、ui 渲染。
  • 微任務(wù)包括:Promise.then/.catch/.finally、queueMicrotask、MutationObserver。

事件循環(huán)執(zhí)行流程如下:

  1. 執(zhí)行一個(gè)宏任務(wù)(比如主代碼塊)
  2. 執(zhí)行所有當(dāng)前可用的微任務(wù)(全部清空)
  3. 渲染頁面(如果需要)
  4. 執(zhí)行下一個(gè)宏任務(wù)

所以,即使微任務(wù)是在宏任務(wù)之后添加的,它們也會在下一個(gè)宏任務(wù)之前執(zhí)行完。


如何理解事件循環(huán)的實(shí)際意義?

理解事件循環(huán)不只是理論,它直接影響我們在實(shí)際開發(fā)中如何安排異步邏輯。

例如:

  • 如果你希望某個(gè)操作延遲執(zhí)行,但又不希望阻塞主線程,可以使用 setTimeout(fn, 0)。
  • 如果你希望某些邏輯在當(dāng)前同步代碼結(jié)束后盡快執(zhí)行,應(yīng)該用 Promise.resolve().then(fn)。
  • 避免在微任務(wù)中嵌套太多異步操作,否則可能造成“饑餓”現(xiàn)象,即瀏覽器無法及時(shí)渲染或響應(yīng)用戶操作。

小技巧:如何觀察事件循環(huán)行為?

你可以通過以下方式來觀察事件循環(huán)的行為:

  • 使用瀏覽器開發(fā)者工具打斷點(diǎn),查看執(zhí)行順序。
  • 在控制臺中嘗試組合不同類型的異步任務(wù),比如:
console.log('A');  setTimeout(() => console.log('B'), 0);  Promise.resolve().then(() => console.log('C'));  console.log('D');

觀察輸出順序有助于加深對事件循環(huán)的理解。


基本上就這些。理解事件循環(huán)的關(guān)鍵在于搞清楚宏任務(wù)和微任務(wù)的執(zhí)行順序,以及它們之間的優(yōu)先級關(guān)系。這看起來不復(fù)雜,但在實(shí)際編碼中很容易忽略細(xì)節(jié),特別是當(dāng)你混用多種異步寫法的時(shí)候。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊5 分享