原文: https://blog.csdn.net/sjn0503/article/details/76087631html
簡單來說,總體的js代碼這個macrotask先執行,同步代碼執行完後有microtask執行microtask,沒有microtask執行下一個macrotask,如此往復循環至結束web
-----------------------------------------------------------------------面試
咱們知道 DOM 操做會觸發瀏覽器對文檔進行渲染,如修改排版規則,修改背景顏色等等,那麼這類操做是如何在瀏覽器當中奏效的?至此咱們已經知道了事件循環是如何執行的,事件循環器會不停的檢查事件隊列,若是不爲空,則取出隊首壓入執行棧執行。當一個任務執行完畢以後,事件循環器又會繼續不停的檢查事件隊列,不過在這間,瀏覽器會對頁面進行渲染。這就保證了用戶在瀏覽頁面的時候不會出現頁面阻塞的狀況,這也使 JS 動畫成爲可能, jQuery 動畫在底層均是使用 setTimeout 和 setInterval 來進行實現。想象一下若是咱們同步的執行動畫,那麼咱們不會看見任何漸變的效果,瀏覽器會在任務執行結束以後渲染窗口。反之咱們使用異步的方法,瀏覽器會在每個任務執行結束以後渲染窗口,這樣咱們就能看見動畫的漸變效果了。api
A web worker or a cross-origin iframe
has its own stack, heap, and message queue. Two distinct runtimes can only communicate through sending messages via the postMessage
method. This method adds a message to the other runtime if the latter listens to message
events.promise
--------------------------------------------------------------------分割線--------------------------------------------------------------------------------瀏覽器
放個面試題,拋個磚:網絡
console.log('start') const interval = setInterval(() => { console.log('setInterval') }, 0) setTimeout(() => { console.log('setTimeout 1') Promise.resolve() .then(() => { console.log('promise 3') }) .then(() => { console.log('promise 4') }) .then(() => { setTimeout(() => { console.log('setTimeout 2') Promise.resolve() .then(() => { console.log('promise 5') }) .then(() => { console.log('promise 6') }) .then(() => { clearInterval(interval) }) }, 0) }) }, 0) Promise.resolve() .then(() => { console.log('promise 1') }) .then(() => { console.log('promise 2') })
不着急揭曉答案,先分析app
首先知曉:webapp
js是單線程語言異步
也就是說一次就只能作一件事情。
多數的網站不須要大量計算,程序花費的時間主要集中在磁盤 I/O 和網絡 I/O 上面
雖然SSD讀取很快,但和CPU處理指令的速度比起來也不在一個數量級上,並且網絡上一個數據包來回的時間更慢(注意過遊戲的延遲嗎)
so: 一些cpu直接執行的任務就成了優先執行主線任務,而後須要io返回數據的任務就成了等待被執行的任務
因此纔會有同步任務(synchronous)和異步任務(asynchronous)之分
同步任務:
在主線程上排隊執行的任務,前一個任務執行完畢,才能執行後一個任務;
異步任務:
不進入主線程、而進入」任務隊列」(task queue)的任務,只有」任務隊列」通知主線程,某個異步任務能夠執行了,該任務纔會進入主線程執行。
總之:
只要主線程空了,就會去讀取」任務隊列」,這就是JavaScript的運行機制
任務隊列不止一個,還有 microtasks 和 macrotasks
microtasks:
macrotasks:
whatwg規範:https://html.spec.whatwg.org/multipage/webappapis.html#task-queue
理解了這些定義以後,再看執行原理:
事件循環的順序,決定了JavaScript代碼的執行順序。它從script(總體代碼)開始第一次循環。以後全局上下文進入函數調用棧。直到調用棧清空(只剩全局),而後執行全部的micro-task。當全部可執行的micro-task執行完畢以後。循環再次從macro-task開始,找到其中一個任務隊列執行完畢,而後再執行全部的micro-task,這樣一直循環下去。
還要注意一點:
包裹在一個 script 標籤中的js代碼也是一個 task 確切說是 macrotask。
因此文首面試題的答案爲:
start
promise 1
promise 2
setInterval
setTimeout 1
promise 3
promise 4
setInterval
setTimeout 2
promise 5
promise 6
簡單來說,總體的js代碼這個macrotask先執行,同步代碼執行完後有microtask執行microtask,沒有microtask執行下一個macrotask,如此往復循環至結束