浏览器中的事件循环
浏览器中的事件循环是怎么进行的?
先看以下代码
setTimeout(()=>{
console.log('s1')
Promise.resolve().then(()=>{
console.log('s2')
})
Promise.resolve().then(()=>{
console.log('s3')
})
})
Promise.resolve().then(()=>{
console.log('p1')
setTimeout(()=>{
console.log('s2')
})
setTimeout(()=>{
console.log('s3')
})
})
上面的代码执行结果是怎么样的?
具体过程我们进行下面的分析
浏览器中事件分为宏任务和微任务
-
setTimeout被归为宏任务,Promise.then则归为微任务
-
浏览器对宏任务和微任务的执行顺序是有规则的
- 优先会将同步任务加入队列,微任务加入微任务队列,宏任务加入宏任务队列
- 优先清空微任务队列,清空微任务后,执行下一个宏任务
- 宏任务执行完成后,会再次去清空微任务队列,因为在宏任务中可能存在微任务,会被加入微任务队列
- 再次清空了微任务队列后,会继续重复执行下一个宏任务然后清空微任务队列,直到所有队列都被清空
-
上面代码会按照以下步骤进行事件循环
- 首先浏览器会按从上到下的顺序执行所有同步代码,把宏任务和微任务分别放到不同的队列中
上面代码中t1和p1是同步的,t1是宏任务,放到宏任务队列,p1是微任务,放到微任务队列
- 浏览器会优先执行微任务队列中的任务,所以p1会优先执行,此时p1被首先输出
- p1输出后,在微任务中发现还有两个宏任务s2和s3,这两个任务则被追加到宏任务队列中
- 微任务p1执行完成,弹出队列。此时微任务列队中没有任务了,开始执行宏任务队列中的第一个任务s1,此时输出s1,同时发现s1中还有两个微任务p2,p3,这两个任务则被按顺序添加到微任务队列中
- 此时s1执行完成,弹出队列,将开始执行微任务队列中的任务
- 此时微任务队列中有p2和p3两个任务,按照顺序执行,则会输出p2,p3,同时p2、p3弹出队列
- 此时微任务队列被清空,又会执行宏任务队列中的下一个宏任务,即s2,同理,s3与s2一样,两个任务按顺序依次输出s2、s3并弹出队列
- 最终结果就是依次输出p1、s1、p2、p3、s2、s3
- 首先浏览器会按从上到下的顺序执行所有同步代码,把宏任务和微任务分别放到不同的队列中