Promise & async/aweait的事件循环

25 阅读2分钟

Promise

new Promise(() => {}).then() 中,前面的 new Promise() 这一部分是一个构造函数,这是一个同步任务,后面的 .then()才是一个异步微任务:

new Promise((resolve) => {
    console.log(1)
    resolve()
}).then(()=>{
    console.log(2)
})

console.log(3)
// 1 3 2

async/await 函数

async/await本质上还是基于Promise的一些封装,而Promise是属于微任务的一种

所以在使用await关键字与Promise.then效果类似,await 以前的代码,相当于与 new Promise 的同步代码,await 以后的代码相当于 Promise.then的异步

setTimeout(() => console.log(4))

async function test() {
    console.log(1)
    await Promise.resolve()
    console.log(3)
}

test()
console.log(2)
// 1 2 3 4

demo

function test() {
    console.log(1)
    setTimeout(function(){ // timer1
        console.log(2)
    }, 1000)
}

test();

setTimeout(function(){ // timer2
    console.log(3)
})

new Promise(function(resolve){
    console.log(4)
    setTimeout(function(){ // timer3
        console.log(5)
    }, 100)

    resolve()
}).then(function(){
    setTimeout(function(){ // timer4
        console.log(6)
    }, 0)
    console.log(7)
})

console.log(8)
// 14873652

截屏2024-04-02 下午4.48.35.png

  1. JS是顺序从上而下执行;
  2. 执行到test(),test方法为同步,直接执行 console.log(1) 打印1;
  3. test方法中 setTimeout 为异步宏任务,回调我们把它记做timer1放入宏任务队列;
  4. test方法下面有一个 setTimeout 为异步宏任务,回调我们把它记做timer2放入宏任务队列;
  5. 执行promise, new Promise 是同步任务,直接执行,打印4;
  6. new Promise 里面的 setTimeout 是异步宏任务,回调我们记做timer3放到宏任务队列;
  7. Promise.then 是微任务,放到微任务队列;
  8. console.log(8)是同步任务,直接执行,打印8;
  9. 主线程任务执行完毕,检查微任务队列中有 Promise.then ;
  10. 开始执行微任务,发现有 setTimeout 是异步宏任务,记做timer4放到宏任务队列;
  11. 微任务队列中的 console.log(7) 是同步任务,直接执行,打印7;
  12. 微任务执行完毕,第一次循环结束;
  13. 检查宏任务队列,里面有timer1、timer2、timer3、timer4,四个定时器宏任务,按照定时器延迟时间得到可以执行的顺序,即Event Queue:timer2、timer4、timer3、timer1,依次拿出放入执行栈末尾执行;
  14. 执行timer2, console.log(3) 为同步任务,直接执行,打印3;
  15. 检查没有微任务,第二次Event Loop结束;
  16. 执行timer4, console.log(6) 为同步任务,直接执行,打印6;
  17. 检查没有微任务,第三次Event Loop结束;
  18. 执行timer3, console.log(5) 同步任务,直接执行,打印5;
  19. 检查没有微任务,第四次Event Loop结束;
  20. 执行timer1, console.log(2) 同步任务,直接执行,打印2;
  21. 检查没有微任务,也没有宏任务,第五次Event Loop结束;