同步 & 非同步(2) - event loop & macro / micro task


Posted by TempuraEngineer on 2022-06-23

目錄


Javascript 與 call stack

Javascript是個單執行緒的語言,它只有一個call stack,所以一次只做一件事

Javascript會用call stack的方式來管理execution contexts(執行環境),
call stack會以後進先出的方式執行裡面的任務

(2024/6/4 更新)
stack是有容量限制的,容量取決於執行環境。舉例來說Chrome的call stack為1000層,Node.js則為1024層,stack容量也會受到電腦RAM影響

如果execution contexts的數量大於stack的容量就會發生stack overflow

// 這種遞迴方式就會導致stack overflow

function foo(){
    foo();
}

// Uncaught RangeError: Maximum call stack size exceeded


execution contexts & event queue & event loop

Javascript會建立2種執行環境 - global execution, function execution contexts。

  • global execution
    當瀏覽器載入一個HTML檔案時,開始執行script時,JavaScript引擎會解析該檔案
    並建立全域物件(window)、this、內建物件(Date、RegExp、Array...)

  • function execution contexts
    函式執行環境,即scope的概念
    在函式被呼叫時建立,所以可能有多個

如果是同步函式的話丟進call stack(main thread),然後每個函式由上而下一行一行執行code,非同步函式的話等web API解析完先丟到queue,當JS主執行環境任務全執行完(即call stack空了),會到queue拿一個來執行。event loop即不斷重複前述動作


macro task(宏任務) & micro task(微任務)

javascript-browser-event-loop

  • 宏任務

    • A task is any JavaScript code which is scheduled to be run by the standard mechanisms such as initially starting to run a program, an event callback being run, or an interval or timeout being fired. These all get scheduled on the task queue

    • 會佔用main thread
    • call stack、micro task的event queue都空了後執行
    • 解析HTML、產生DOM、畫面渲染、載入script、setTimeout、setInterval、鍵盤事件、滑鼠事件、network events
  • 微任務

    • A microtask is a short function which is executed after the function or program which created it exits and only if the JavaScript execution stack is empty, but before returning control to the event loop being used by the user agent to drive the script's execution environment.

    • 不會佔用main thread
    • call stack空了後執行
    • 變更DOM、重新渲染畫面、Promise的then、catch(Promise的executor是同步任務)


執行順序

產生DOM、畫面渲染、載入script(宏任務) →同步任務 → 微任務 → 宏任務

// 帶有async的function事實上還是同步函式
// async只意味著該函式內的動作會返回一個Promise物件
async function sayHello(){ 
    console.log('say');

    // 執行到await會暫停,web API解析完就丟到micro task queue,同步任務結束再執行
    await Promise.resolve(); // 微任務,
    console.log('hello');
}

function foo(){ // 同步任務
    console.log('foo');
}

console.time();
setTimeout(() => { // 宏任務
    console.log('setTimeout');
}, 100)
console.timeEnd();
sayHello();
foo();

// 執行結果如下
// say
// foo
// hello
// setTimeout


🖊名詞解釋

(2024/6/4更新)

名詞 解釋 其他
call stack(execution stack) 呼叫堆疊,可以想成一個裝了要執行的函式的容器 stack,一種資料結構,遵循後進先出的原則。
task queue (event queue、callback queue) 事件佇列,一個裝了待執行的非同步函式的容器 queue,一種資料結構,遵循先進先出的原則
main thread 處理同步任務的thread,大約等於call stack
memory heap 記憶體堆疊,決定object在記憶體的配置
event loop
宏任務 會佔用main thread, 各自裝到不同的event queue
微任務 不佔用main thread, 各自裝到不同的event queue


📖參考資料

Day13 - Event Queue & Event Loop 、Event Table
所以說event loop到底是什麼玩意兒?
透過程式範例,熟悉 JS 執行流程的關鍵:Event Loop

解釋 Event Loop ( 下 ) --- Task Queue ( Callback Queue )
Javascript 的執行環境 (Execution context) 與堆疊 (Stack)
JavaScript Call Stack

Using microtasks in JavaScript
JS 時間循環 - 宏任務與微任務
What are Micro tasks and Macro tasks in JavaScript?
Understand once-the macro tasks and micro tasks of the JS event loop
async and tasks


#micro task #macro task #Event Loop #微任務 #宏任務 #事件循環







Related Posts

D27_ALG 101-Unit 6

D27_ALG 101-Unit 6

[Linux] Vmmem 記憶體佔用過高(wsl, ubuntu)

[Linux] Vmmem 記憶體佔用過高(wsl, ubuntu)

反射方法操作

反射方法操作


Comments