瀏覽器的事件循環分為 macrotask 和 microtask,瀏覽器先從 macrotask 取出一個任務執行,再執行 microtask 內的所有任務,接着又去 macrotask 取出一個任務執行,這樣一次循環。
marcotask 的本質是瀏覽器多個線程之間通信的一個消息隊列;在 chrome 里,每個頁面都對應一個進程,該進程又有多個線程,比如 js 線程、渲染線程、io 線程、網絡線程、定時器線程等等,這些線程之間的通信是通過向對象的任務隊列中添加一個任務(postTask) 來實現的;
瀏覽器的各種線程都是常駐線程,他們運行在一個 for 死循環里面,每個線程都有屬於自己的若干任務隊列,線程自己或者其它線程都可能通過 postTask 向這些任務隊列添加任務,這些線程會不斷的從自己的任務隊列中取出任務執行,或者把處於睡眠狀態直到設定的時間或者是有人 postTask 的時候把它喚醒;
microtask 是確確實實存在的一個隊列,microtask 是屬於當前線程的,而不是其他線程 postTask 過來的任務。只是延遲執行了而已,比如 Promise.then、mutationObserve 都屬於這種情況;
宏任務隊列可以有多個,微任務隊列只有一個;主線程上的任務就是第一個宏任務,即剛進來時候的 script;能夠建立宏任務的有: script、setTimeOut、setInterval、requestAnimationFrame 等;會建立微任務的有:promise的回調、process.nextTick 等;當有一個宏任務隊列執行完畢后,會執行微任務隊列中的全部內容,然后執行另一個宏任務,如此反復;