首先我们来看一段代码:
console.log("script start!")
setTimeout(function () {
console.log("setTimeout");
},0);
new Promise(function (resolve) {
console.log("promise1");
resolve();
console.log("promise2");
}).then(function () {
console.log("promise then")
});
console.log("script end!")
它的输出应该是:
script start!
promise1
promise2
script end!
promise then
setTimeout
为什么呢
我们先来看宏任务与微任务:
宏任务(macro-task):同步script(整体代码),setTimeout回调函数,setInterval回调函数,I/O,UI rendering(即我们对css进行更改时,造成的页面重新渲染)
微任务(micro-task):process.nextTick;Promise 回调函数,Object.observe,MutationObserver
执行顺序是这样的:
- 首先 JavaScript 引擎会执行一个宏任务,注意这个宏任务一般是指主干代码本身,也就是目前的同步代码
- 执行过程中如果遇到微任务,就把它添加到微任务任务队列中
- 宏任务执行完成后,立即执行当前微任务队列中的微任务,直到微任务队列被清空
- 微任务执行完成后,开始执行下一个宏任务
- 如此循环往复,直到宏任务和微任务被清空
如图所示:
这个模型,就叫作 Event Loop。Event Loop 只是一个理论模型,在不同的环境有不同的实现。比如浏览器和 NodeJS 就是基于不同的技术实现了各自的 Event Loop。
部分内容来源:imooc