每日挑戰,從Javascript面試題目了解一些你可能忽略的概念 – Day24

tags: ItIron2021 Javascript

前言

對點進來的你說一下,恭喜你撐到今天! 非同步的最後一個問題,之後的最後幾天就會進入到一些比較零碎的應用題目囉! 馬上來看一下最後的非同步題目吧! 順帶一提,這個題目我後來才發現原來是之前在it邦的另一個鐵人賽系列文就有看過了..面試官可以不要直接把看到的題目拿來考嗎,至少換個例子吧! 文章連結我會附在最後,是個非常棒的系列文!

本日題目與解釋

請問下方的程式碼輸出結果為?

setTimeout(() => alert("timeout"));

Promise.resolve()
  .then(() => alert("promise"));

alert("global ex. context");
thinking-day24

看到這邊你應該迫不及待的要回答了,這很簡單嘛!

阿不就考同步 VS 非同步的執行順序,event loop我被虐了幾次了還不懂嗎?

先處理同步程式碼再處理非同步就好了嘛! 跳出的alert順序肯定是這樣的!

global ex. context
timeout
promise

但實際上卻是….

global ex. context
promise
timeout

你現在的心情大概是這樣吧,我懂

wtf

其實原因是因為瀏覽器在處理非同步時其實還有細節我們之前沒有提到,就是所謂的macro task & micro task,這兩個名詞中文老樣子沒有我特別滿意的翻譯(許多人叫宏任務&微任務,但..我聽不習慣),下面還是就用原文來說明吧!

老樣子解釋觀念不是我的重點,這邊只是簡單的說明!
實際上瀏覽器在執行程式碼時會是以下的流程

micro task vs macro task

簡單來說就是分同步任務又再細分為macro task & micro task

常見的macro task有

  • 滑鼠、鍵盤事件
  • setTimeout/setInterval
  • 執行script

而常見的micro task有

  • promise(注意,是取值的部份,也就是.then & .catch才是非同步)
  • DOM操作

兩種任務的執行時間點並不相同,每執行完一個macro task,它就會停下來看一下micro task queue中是不是有還沒執行的micro task並一口氣將全部的micro task執行完! 接著在繼續跑渲染之類的流程後再次執行下一個macro task,並反覆這樣的流程,所以簡單來說

可在一次的event loop就執行多個micro task,但只能執行一個macro task

所以只要能分辨macro task/micro task就沒有問題囉! 理解這點之後回頭看一下題目,promise取值很明顯屬於micro、而setTimeout屬於macro,但別忘記執行script也算一個macro task,也就是說流程是這樣的

   run script (跑完一個macro task,該清空micro task queue了)
=> promise (清空micro task queue,該跑下一個macro task了)
=> setTimeout

最終就造成你看到的結果囉,是不是沒有想像中這麼難懂呢?

今天會附上兩篇很棒的文章,若想進一步了解相關觀念或題目我是非常推薦的!

本日核心觀念與總結

核心觀念

macro task vs micro task、event loop

總結

  • 了解那些屬於macro task & micro task
  • 了解兩者在執行時間點上的差別
  • 了解一個loop中只能執行一個macro task,但micro task可以執行多個

推薦文章

JS 原力覺醒Day15 – Macrotask 與MicroTask

聊聊JavaScript非同步中的macrotask和microtask

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s