1. 同步任务
const num1 = 1;
const num2 = 2;
const num3 = 3;
console.log(num1); // 1
console.log(num2); // 2
console.log(num3); // 3
从上往下一行一行执行。
2. 异步任务
console.log(1);
setTimeout(() => {
console.log(2);
}, 0)
console.log(3);
结果为: 1 3 2
3. 宏任务、微任务
宏任务:
- setTimeout
- setInterval
- Ajax
- DOM事件
- I/O
- script标签中的整体代码
微任务:
- new Promise()
- new MutaionObserver()
下面我们看一个例子,然后我们根据结果再解释就会有种恍然大明白的感觉了:
console.log(1);
Promise.resolve(2).then(res => {
console.log(2);
})
setTimeout(() => {
console.log(3)
}, 0)
Promise.resolve(4).then(res => {
console.log(4)
})
console.log(5);
setTimeout(() => {
console.log(7)
}, 0)
结果为: 1 5 2 4 3 7
为什么结果不是1 5 2 3 4 7呢?
其实上面的所有内容其实都围绕一个执行机制——事件循环机制(event loop)
*** 4. 事件循环机制(event loop)
- js引擎会从上到下逐行进行解析;
- 将其中的同步任务按照执行顺序排列到执行栈中,所有的异步任务会放到"任务队列"中;
- 在所有的同步任务执行结束后,在确保没有同步任务的时候,然后检查"任务队列"中是否有任务,如果有,就将第一个事件对应的回调,推到执行栈中执行;
- ==注意:==异步任务分宏任务和微任务两种类型,微任务比宏任务的执行时间要早,所以会优先把所有的微任务放到执行栈中执行。在执行任何一个宏任务以前(不是队列,是一个宏任务),都会查看微任务队列是否有任务需要清空,也就是宏任务执行以前,必须保证微任务是空的。
所以从上面的代码例子中可以得出:
先把同步任务执行,得到 1,5, 然后依次执行微任务(Promise),得到 2, 4,最后执行宏任务(setTimeout),得到3, 7。所以得出1 5 2 4 3 7