天天看點

js事件循環Event Loop機制浏覽器環境下js引擎的事件循環機制node環境下的事件循環機制參考

文章目錄

  • 浏覽器環境下js引擎的事件循環機制
    • 執行棧與事件隊列
    • macro task與micro task
  • node環境下的事件循環機制
    • 與浏覽器環境的差別
    • 事件循環模型
    • 事件循環各階段
  • 參考

浏覽器環境下js引擎的事件循環機制

執行棧與事件隊列

  • 當javascript代碼執行的時候會将不同的變量存于記憶體中的不同位置:堆(heap)和棧(stack)中來加以區分。堆裡存放着一些對象,而棧中則存放着一些基礎類型變量以及對象的指針。而執行棧與此不同。
  • 執行同步方法時:當我們調用一個方法的時候,js會生成一個與這個方法對應的執行環境(context),又叫執行上下文。這個執行環境中存在着這個方法的私有作用域,上層作用域的指向,方法的參數,這個作用域中定義的變量以及這個作用域的this對象。當一系列同步方法被依次調用的時候,因為js是單線程的,同一時間隻能執行一個方法,于是這些方法被排隊在一個單獨的地方。這個地方被稱為執行棧。
  • 執行異步方法時:異步方法會被加入事件隊列中,等待目前執行棧中的所有任務都執行完畢,主線程處于閑置狀态時,主線程會去查找事件隊列,并把這個事件對應的回調放入執行棧中,然後執行其中的同步代碼…,如此反複,這樣就形成了一個無限的循環。這就是這個過程被稱為“事件循環(Event Loop)”。

    總結:事件循環指得是,執行同步方法和異步方法時,同步方法加入執行棧,異步方法加入事件隊列。當執行棧所有任務完成時再查找事件隊列,将事件回調加入執行棧繼續執行,形成一個循環過程。

macro task與micro task

異步任務被分為兩類:微任務(micro task)和宏任務(macro task)。

  • 微任務:new Promise()、new MutaionObserver()
  • 宏任務:setInterval()、setTimeout()

    同一次事件循環中,微任務永遠在宏任務之前執行。

node環境下的事件循環機制

與浏覽器環境的差別

在node中,事件循環表現出的狀态與浏覽器中大緻相同。不同的是node中有一套自己的模型。node中事件循環的實作是依靠的libuv引擎。我們知道node選擇chrome v8引擎作為js解釋器,v8引擎将js代碼分析後去調用對應的node api,而這些api最後則由libuv引擎驅動,執行對應的任務,并把不同的事件放在不同的隊列中等待主線程執行。 是以實際上node中的事件循環存在于libuv引擎中。

事件循環模型

┌───────────────────────┐

┌─>│ timers │

│ └──────────┬────────────┘

│ ┌──────────┴────────────┐

│ │ I/O callbacks │

│ └──────────┬────────────┘

│ ┌──────────┴────────────┐

│ │ idle, prepare │

│ └──────────┬────────────┘ ┌───────────────┐

│ ┌──────────┴────────────┐ │ incoming: │

│ │ poll │<──connections─── │

│ └──────────┬────────────┘ │ data, etc. │

│ ┌──────────┴────────────┐ └───────────────┘

│ │ check │

│ └──────────┬────────────┘

│ ┌──────────┴────────────┐

└──┤ close callbacks │

└───────────────────────┘

事件循環各階段

外部輸入資料–>輪詢階段(poll)–>檢查階段(check)–>關閉事件回調階段(close callback)–>定時器檢測階段(timer)–>I/O事件回調階段(I/O callbacks)–>閑置階段(idle, prepare)–>輪詢階段…

參考

https://zhuanlan.zhihu.com/p/33058983

繼續閱讀