js事件循环机制(event loop)之宏任务/微任务
微任务和宏任务属于一个队列,主要区别在于它们的执行顺序(宏任务执行完如果有可执行的微任务则执行完微任务才会继续执行下一个宏任务)
宏任务:包括整体代码script,setTimeout,setInterval,setImmediate。用户的一些操作的回调,如鼠标点击事件,键盘事件,ajax请求,dom操作等
微任务:原生Promise(有些实现的promise将then方法放到了宏任务中)、process.nextTick、MutationObserver
例如:
<script> console.log(222) Promise.resolve().then(() => { console.log(11) }) console.log(444) </script> <script> console.log(333) </script>
打印结果是:
解释:首先script是一个宏任务,两个script标签是两个宏任务,按照事件循环的规则执行顺序 第一个宏任务执行完成(222,444)==》执行存在的微任务(11)==》执行第二个宏任务(333)
事件循环:JS 会创建一个类似于
while (true)
的循环,每执行一次循环体的过程称之为Tick
。每次Tick
的过程就是查看是否有待处理事件,如果有则取出相关事件及回调函数放入执行栈中由主线程执行。待处理的事件会存储在一个任务队列中,也就是每次Tick
会查看任务队列中是否有需要执行的任务。主线程:JS 只有一个线程,称之为主线程。而事件循环是主线程中执行栈里的代码执行完毕之后,才开始执行的。所以,主线程中要执行的代码时间过长,会阻塞事件循环的执行,也就会阻塞异步操作的执行。只有当主线程中执行栈为空的时候(即同步代码执行完后),才会进行事件循环来观察要执行的事件回调,当事件循环检测到任务队列中有事件就取出相关回调放入执行栈中由主线程执行。