1.什麼是事件循環?
JavaScript有一個基於事件循環的併發模型,事件循環負責執行代碼、收集和處理事件以及執行隊列中的子任務。這個模型與其它語言中的模型截然不同,比如 C 和 Java。這是來自MDN的介紹。
簡單來講就是js運行處理代碼的一套機制。
2.微任務Microtasks和宏任務tasks
宏任務:一般是指js引擎
與宿主環境
發生通信產生的回調任務,常見的宏任務有run <script>
(同步的代碼執行)、setTimeout
、setInterval
、setImmediate
(node環境中)、I/O
、UI交互
。
微任務:一般是宏任務在線程中執行產生的回調,常見的微任務有Promise
、MutationObserver
、process.nextTick
(node環境)。
3.執行流程
簡單來講就是在宏任務中,先執行一遍,遇見微任務,將微任務推到隊列,再執行所有微任務。拿簡單的代碼舉例
<script>
(function() {
console.log('start');
setTimeout(function() {
console.log('setTimeout1');
});
Promise.resolve().then(function() {
console.log('promise1');
})
setTimeout(function() {
console.log('setTimeout2');
}, 0);
console.log('end');
})();
</script>
首先執行第一個宏任務run script
,執行裏邊的匿名函數。首先打印start
,遇見setTimeout
推入到宏任務隊列,再遇見Promise
推到微任務隊列,再遇見setTimeout
推到宏任務隊列,打印end
。目前的隊列如圖:
宏任務 | 微任務 |
---|---|
setTimeout | Promise |
setTimeout |
當前的微任務還沒執行完畢所以執行Promise,打印promise1
;然後再執行下一個宏任務setTimeout
打印出setTimeout1
,因爲這個宏任務中沒有微任務,所以接着執行下一個宏任務setTimeout,打印出setTimeout2
。
再來一個頭條的異步筆試題,你要是能答對這個,相信事件循環機制就已經掌握了。
<script>
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');
</script>
不懂得地方可以去翻看執行流程或者留言,這道題的答案是:script start、async1 start、async2、promise1、script end、async1 end、promise2、setTimeout。