首先咱們要知道關於JavaScript的一些規則:git
同步任務都在主線程上執行,造成一個執行棧。當主線程執行完以後,運行微任務(micro-task)隊列的任務直到爲空,更新UI渲染(會根據瀏覽器的邏輯,決定要不要立刻執行更新),而後再運行宏任務(macro-task)隊列的任務直到爲空......流程以下:github
(主線程上的執行棧同步任務,能夠視爲是第一個macro-task隊列) macro-task -> micro-task(若是存在) -> 更新UI渲染
如此無限循環上面的流程,是爲JavaScript的Event Loop機制。chrome
宏任務(macro-task),宏任務隊列能夠有一個或者多個。每一個任務都有一個任務源(task source),源自同一個任務源的 task 必須放到同一個任務隊列,從不一樣源來的則被添加到不一樣隊列。promise
宏任務:script(全局任務), setTimeout, setInterval, setImmediate, I/O, UI rendering.瀏覽器
微任務(micro-task),微任務在渲染更新前,macro-task以後執行。
關於async和await,由於async await 自己就是promise+generator的語法糖。因此await後面的代碼是microtask。實際上await是一個讓出線程的標誌。await後面的表達式會先執行一遍,將await後面的代碼加入到microtask中,而後就會跳出整個async函數來執行後面的代碼。異步
微任務:process.nextTick, Promise, Object.observer, MutationObserver,await.async
async function async1() { console.log('async1 start'); await async2(); console.log('async1 end'); } async function async2() { console.log('async2'); } console.log('script start'); setTimeout(function () { console.log('setTimeout'); }, 0) async1(); new Promise(function (resolve) { console.log('promise1'); resolve(); }).then(function () { console.log('promise2'); }); console.log('script end');
流程以下:函數
完整結果以下:oop
/** *script start *async1 start *async2 *promise1 *script end *async1 end *promise2 *setTimeout */
該結果基於chrome 版本 72.0.3626.121。由於async await標準有所改變,因此稍老版本的瀏覽器結果可能不一致。spa
參考:
https://jakearchibald.com/201...
https://github.com/Advanced-F...