JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。所以所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
消息队列:消息队列是一个先进先出的队列,它里面存放着各种消息。
事件循环:事件循环是指主线程重复从消息队列中取消息、执行的过程。
JS 中分为两种任务类型: 宏任务和微任务
在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在宏任务的队列中取出第一个任务,执行完毕后取出微任务队列中的所有任务顺序执行;之后再取宏任务队列的任务,周而复始,直至两个队列的任务都取完。
宏任务和微任务的执行过程如下:
宏任务一般是:script,setTimeout,setInterval、setImmediate ; 微任务:原生Promise
例子:
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
new Promise(resolve => {
console.log(3)
setTimeout(() => {
console.log(4)
resolve()
}, 0)
}).then(() => {
console.log(5)
})
console.log(6)
复制代码
宏任务:2 4
微任务:5
- 先遇到 console 直接 打印 1
- 遇到 setTimeout 将 2 放到宏任务队列
- 再向下执行遇到promise , 直接执行打印 3 , 再遇到 setTimeout 将 4 放到宏任务队列,遇到 then 将 5 放到微任务队列
- 遇到 console 直接打印 6
- 第一轮执行结束, 应该执行微任务队列打印 5 , 但是 then 是 promise resolve() 的语法糖, 只有执行了 resolve(), 才能执行打印 5
- 因为没有其他的微任务,所以去执行宏任务队列,依次打印 2 4 , 再执行 resolve() 打印 5
执行结果: 1 3 6 2 4 5
练习题
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise3');
resolve();
}).then(function() {
console.log('promise4');
});
console.log('script end');
复制代码
执行结果: script start –》async1 start –》promise1 –》 promise3 –》 script end –》 promise2 –》async1 end –》 promise4 –》 setTimeout
宏任务:setTimeout
微任务:promise2 , async1 end , promise4
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END