js运行机制
  首先我们知道,在js运行的时候,会有一个主线程,这个主线程在由上向下执行js代码的时候,如果遇到异步任务,会把异步任务交给异步线程去处理,异步任务执行之后,如果有回调,就会把回调放到任务队列里去.等待主线程执行栈里的东西执行完了,就用任务队列里从前往后取需要执行的任务,放到主线程里执行.由此形成一个循环.这个循环就是EventLoop.
  在这里要提到一点,主线程里面执行的任务和任务队列里的任务都是宏任务,每执行一个宏任务V8引擎就会创建一个栈,并且V8会为每一个宏任务创建一个微任务,等宏任务执行栈里的内容执行完了,会先去执行这个微任务,等微任务再执行完了,就销毁执行栈,并且去任务队列里取下一个宏任务执行.

 

宏任务包括:

  • script(整体代码)
  • setTimeout, setInterval, setImmediate,
  • I/O
  • UI rendering

微任务包括:

  • process.nextTick
  • Promise
  • Object.observe(已废弃)
  • MutationObserver(html5新特性)

async函数的本质:

  async函数还是基于Promise的一些封装,而Promise是属于微任务的一种;因此会把await func()后面的所有代码放到Promise的then回调函数中去

  举个例子:

  

async function async1(){
    console.log('async1 start')
    await async2()
    console.log('async1 end')
}

async function async2(){
    console.log('async2')
}

console.log('script start')
async1()

console.log('script end')
 
//script start
//async1 start
//async2
//script end
//async1 end
 

   以上代码可以写成这样:

  

async function async1() {
    console.log('async1 start')
    new Promise(function(resolve){
        console.log('async2')
        resolve()
    }).then(function(){
        console.log('async1 end')
    })
}
console.log('script start')
async1()
console.log('script end')

  以上都了解完之后 做个面试题:

async function async1(){
    console.log('async1 start')
    await async2()
    console.log('async1 end')
}

async function async2(){
    console.log('async2')
}

console.log('script start')

setTimeout(function(){
    console.log('setTimeOut')
}, 0)

async1()

new Promise(function(resolve){
    console.log('promise1') 
    resolve()
}).then(function(){
    console.log('promise2') 
})

console.log('script end')

结果是:

1 //script start
2 //async1 start
3 //async2
4 //promise1
5 //script end
6 //async1 end
7 //promise2
8 //setTimeOut

解析过程就是:

    1. 第一轮循环开始
    2. 打印script start
    3. 发现setTimeout,放入宏任务1
    4. 打印async1 start
    5. 打印async2
    6. 把await async2函数后面的回调放入微任务1
    7. 打印promise1
    8. 把then中的函数放入微任务2
    9. 打印script en
    10. 调用栈清空,开始执行微任务1,打印async1 end
    11. 执行微任务2,打印promise2
    12. 微任务执行完,第一轮循环结束
    13. 开始宏任务1,打印setTimeOut

参考链接:https://xieyufei.com/2019/12/30/Quiz-Eventloop.html