先運行下面的一段代碼:segmentfault
console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); console.log('script end'); //"script start" //"script end" //"setTimeout"
這裏一看,setTimeout的延時爲 0 ,那麼是否是程序執行到這裏以後就當即執行setTimeout裏面的函數呢?其實不是的.
這是由於 JavaScript 主線程擁有一個 執行棧 以及一個 任務隊列,主線程會依次執行代碼,當遇到函數時,會先將函數 入棧,函數運行完畢後再將該函數 出棧,直到全部代碼執行完畢。promise
那麼遇到 WebAPI(例如:setTimeout
, AJAX
)這些函數時,這些函數會當即返回一個值,從而讓主線程不會在此處阻塞。而真正的異步操做會由瀏覽器執行,瀏覽器會在這些任務完成後,將事先定義的回調函數推入主線程的 任務隊列 中。瀏覽器
而主線程則會在 清空當前執行棧後,按照先入先出的順序讀取任務隊列裏面的任務。異步
那麼咱們來看一下上面程序的執行順序:函數
// 1. 開始執行 console.log('script start'); // 2. 打印字符串 "script start" setTimeout( function() { // 5. 瀏覽器在 0ms 以後將該函數推入任務隊列 // 而到第5步時纔會被主線程執行 console.log('setTimeout'); // 6. 打印字符串 "setTimeout" }, 0 ); // 3. 調用 setTimeout 函數,並定義其完成後執行的回調函數 console.log('script end'); // 4. 打印字符串 "script end" // 5. 主線程執行棧清空,開始讀取 任務隊列 中的任務
以上就是瀏覽器的異步任務的執行機制,核心點爲:oop
Macrotask 和 microtask 都是屬於上述的異步任務中的一種,咱們先看一下他們分別是哪些 API :線程
macrotasks: setTimeout, setInterval, setImmediate, I/O, UI renderingcode
microtasks: process.nextTick, Promises, Object.observe(廢棄), MutationObserverserver
setTimeout 的 macrotask ,和 Promise 的 microtask 有什麼不一樣呢? 咱們經過下面的代碼來展示他們的不一樣點:對象
console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); }); console.log('script end'); //"script start" //"script end" //"promise1" //"promise2" //"setTimeout"
在這裏,setTimeout的延時爲0,而Promise.resolve()也是返回一個被resolve了promise對象,即這裏的then方法中的函數也是至關於異步的當即執行任務
這裏的運行結果是Promise的當即返回的異步任務會優先於setTimeout延時爲0的任務執行。
緣由是任務隊列分爲 macrotasks 和 microtasks,而Promise中的then方法的函數會被推入 microtasks 隊列,而setTimeout的任務會被推入 macrotasks 隊列。在每一次事件循環中,macrotask 只會提取一個執行,而 microtask 會一直提取,直到 microtasks 隊列清空。
注:通常狀況下,macrotask queues 咱們會直接稱爲 task queues,只有 microtask queues 纔會特別指明。
那麼也就是說若是個人某個 microtask 任務又推入了一個任務進入 microtasks 隊列,那麼在主線程完成該任務以後,仍然會繼續運行 microtasks 任務直到任務隊列耗盡。
而事件循環每次只會入棧一個 macrotask ,主線程執行完該任務後又會先檢查 microtasks 隊列並完成裏面的全部任務後再執行 macrotask
參考:清蒸不是水煮 的文章
阮一峯 - JavaScript 運行機制詳解:再談Event Loop
Philip Roberts - Help,I’m stuck in an event loop