初探事件循环-Event Loop

  最近面试遇到这样一道面试题:

console.log(1);
setTimeout(()=> {
    console.log(2);
},1000);
setTimeout(() => {
    console.log(3);
},0);
new Promise((resolve, reject) => {
    console.log(4);
    resolve();
}).then(() => {
    console.log(5);
}).then(() => {
    console.log(6)
})
console.log(7);
new Promise((resolve, reject) => {
    console.log(8);
    resolve();
}).then(() => {
    console.log(9);
}).then(() => {
    console.log(10)
})

问:上述代码的输出结果是啥?
答:1、4、7、8、5、9、6、10、3、2

  为什么输出结果是上边这样的顺序呢?promise的then回调函数会在setTimeout(function () {}, 0);之前输出呢?我们可以先从事件循环说起:
  Javascript是单线程的,在执行时,会先执行同步代码,遇到异步执行的代码,会先将代码放入到任务队列中,主线程的代码执行完毕,就会从任务队列中取出任务执行。 按照当前描述,Javascript会先执行同步代码,即console.log()函数和promise实例对象;然后,将其余的异步函数加入到任务队列中。
  接下来,promise的then回调和setTimeout函数,都是异步执行,那么为什么promise的then回调会在setTimeout之前输出呢?原因如下:
  在JavaScript中,任务队列不止有一个,包含:MacroTask和MicroTask,在Javascript中可以包含多个MacroTask,但是只能包含一个MicroTask,在代码执行中,异步事件会根据自己的类型加入到不同的任务队列中。
  Javascript开始执行事件时,会先清空函数调用栈,然后先执行MicroTask任务,再执行MacroTask;在执行这两个任务队列时,会先将MicroTask任务队列清空,然后再去执行MacroTask队列中的一个。然后循环执行…

MicroTask: Promise、Object.observe
MacroTask: setTimeout、setInterval、setImmediate、UI渲染

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章