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。