浏览器事件循环

155 阅读2分钟

JavaScript 中分为执行栈和任务队列,而任务队列又分为微任务( MicroTask )与宏任务( MacroTask ) MicroTask微任务:Promise、MutationObserve、Process.nextTick( node 才有)

MacroTask宏任务:setTimeout、setInterval、IO回调、页面交互事件、setImmediate( node )、MessageChannel

注意:在浏览器中,执行优先级为 同步代码 > 微任务 > 宏任务 在浏览器中,首先会将同步代码加入执行栈一次弹出执行,当在执行过程中,遇到异步事件不会一直等待到事件完成,而是将异步任务挂起,继续执行同步代码,当异步任务返回结果时,将异步任务的回调事件加入到一个事件队列当中去,这个事件队列里的任务并不会立即执行,而是等同步任务全部执行完,再依次执行事件队列里的事件,在这个过程中,会优先取出微任务(MicroTask),然后取出宏任务(MacroTask) 注意:微任务队列会一次性全部执行清空 console.log('script start'); setTimeout(function () { console.log('setTimeout'); }, 0); new Promise((resolve,reject)=>{ console.log('promise'); resolve(); }).then(function () { console.log('promise1'); }).then(function () { console.log('promise2'); }).then(function () { console.log('promise3'); }); console.log('script end'); //执行结果

首先将同步代码推入执行栈执行,首先输出 'script start' ,然后将setTimeout挂起推入宏任务队列,这里注意 new Promise() 中的代码是同步代码,会直接执行,输出 'promise' ,然后将 then 里的回调函数推入微任务队列,事件循环,检查微任务队列,此时已经有 Promise 的回调函数,推入执行栈,输出 'promise1' 。Promise还有回调函数,推入微任务事件队列,执行栈结束。Promise 还有回调函数,推入微任务事件队列,执行栈结束,重复事件循环,依次输出 'promise2' , 'promise3' ,继续循环,此时微任务队列没有任务,检查宏任务队列,将 setTimeout 推入执行栈,输出 'setTimeout' ,至此,事件循环结束。