淺談JavaScript的事件循環機制(Event Loop)- 瀏覽器篇|8月更文挑戰

前言

咱們先來看個實際中的場景:javascript

在瀏覽器上打印出1~100萬。java

對於這個需求,咱們第一個反應的代碼是這樣的:瀏覽器

for (let i = 0; i < 100 * 10000; i++) {
    const div = document.createElement("div");
    div.innerText = i;
    document.body.append(div);
  }
複製代碼

看着好像沒問題,固然這裏有的同窗會說,你這裏操做了100萬次dom,性能損耗很嚴重。這是一個問題,可是這個不是本文討論的重點。markdown

咱們實際運行一下這段代碼,發現一開始的時間(很短)會沒法正常作交互,好比鼠標懸浮,選中文字等操做。那麼爲何會形成這個現象呢?不急,咱們一步步分析。app

瀏覽器的渲染機制

以Chrome爲例,一個標籤頁獨佔一個渲染進程,而JavaScript解釋線程是屬於這個渲染進程內的。dom

咱們先聊下前置知識,JavaScript執行和屏幕渲染是互斥的,緣由是屏幕渲染須要根據DOM結構,而JavaScript是有能力修改DOM的,因此會在JavaScript執行完畢後,執行渲染動做。通常來講,屏幕的渲染是60HZ,差很少16ms須要切換一張圖片,人眼纔不會意識到卡頓。異步

那麼咱們再回來看剛剛的代碼async

for (let i = 0; i < 100 * 10000; i++) {
  }
複製代碼

結論很明顯了,這句代碼的執行明顯超過了16ms!!!oop

事件循環機制

事件循環機制(Event Loop)就是爲了解決這個問題而提出的。性能

簡單來講,咱們把大任務切成了多個小任務,讓這些任務的執行和渲染流程交錯進行。

計算100萬個(1s) => 屏幕渲染

計算10萬個(0.1s) => 屏幕渲染 => 計算10萬個(0.1s) => 屏幕渲染 => 計算10萬個(0.1s) => ...

這裏就不貼出具體的代碼實現了,感興趣的同窗能夠本身動手寫一下。

再探事件循環機制

事件循環機制(Event Loop)出現後,JavaScript的執行任務分爲了兩類:同步任務和異步任務。而異步任務,又分紅了兩類:

  • 宏任務(Macrotask)總體代碼定時器I/O
  • 微任務(Microtask)PromiseMutationObserverobserver

這裏咱們須要注意一點,Promise自己是同步代碼,可是它的回調then catch是異步

new Promise((res, rej) => {
    res('ok') // 同步任務
  }).then((result) => {
    console.log(result) // 異步任務中的微任務
  })
複製代碼

其實咱們會好奇,爲何是分紅這兩類?爲何不是三類或者一類?其實這是一種權衡的策略。宏任務的定義爲耗時長的任務,微任務爲耗時短的任務。在實際執行中,須要執行的任務分紅多,因此就會有優先級的問題,其實宏任務和微任務的制定就是一種折中,爲了權衡執行時間和運行效率。

優先級問題

咱們剛剛提到了優先級的問題,那咱們就來展開聊聊。通常狀況下,微任務的執行優於宏任務。爲何是通常狀況下呢?咱們來看下這段代碼:

for(let i = 0; i < 10; i++) {
    setTimeout(() => {
      console.log('宏任務開始')
      for (let j = 0; j < 10; j++) {
        microtask();
      }
    })
  }

  function microtask() {
    return new Promise(async (res) => {
      console.log('微任務開始')
      await microtask();
      res();
    })
  }
複製代碼

註冊10個宏任務 => 運行第1個宏任務 => 註冊10個微任務 => 微任務執行過程當中又註冊了微任務 => 微任務執行過程當中又註冊了微任務 => ...

這是一個微任務的死循環,若是按微任務的執行優於宏任務的論據,宏任務是不可能觸發第二個的,由於微任務隊列一直在被push。

可是實際狀況下,咱們是能夠看到第二個宏任務開始的。這是爲何呢?實際上是Chrome V8作的一個小策略,在微任務過多的時候,會執行下一個宏任務。

小結

咱們經過了開頭的一個小例子,引入了事件循環機制(Event Loop),而執行任務分爲了兩類:同步任務和異步任務。而異步任務,又分紅了兩類:宏任務和微任務。通常狀況下,微任務的執行優於宏任務。當在極端場景下,好比微任務實在是太多了,Chrome V8會先執行宏任務。

最後打波小廣告,美團校招社招內推,不限部門,不限崗位,不限投遞數量,海量hc,快來快來~

相關文章
相關標籤/搜索