浅聊JS经典异步问题

代码如下

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

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

console.log('script--start')

setTimeout (() => {
    console.log('setTimeout')
},0)

async1()

new Promise ((resovle,reject) => {
    console.log('promise--1');
    resovle()
}).then(() => {
    console.log('promise--2')
}).catch(() => {
    console.log('promise--reject')
})

console.log('script--end')

浅分析

        1.根据js代码从上往下执行原理,首先函数定义时不执行,所以最先执行的是console.log('script--start'),所以第一个先打印的是'script--start'

        2.接下来代码执行到setTimeout,此时setTimeout作为异步且为宏任务,丢入异步队列中,继续往下走,此时调用async1(),函数被调用时,会立马执行函数体,所以此时执行console.log('async1--start'),所以第二个打印的是'async1--start'

        3.再接下来到 await async2(),此时会立即执行函数体async2(),所以第三个打印'async2--',此时await async2()后面的代码全部做异步处理,作为微任务丢入异步队列

       4. 继续往下走执行new Promise()代码,promise传入的函数体会立即执行,所以第四个打印的是'promise--1',然后调用resovle(),此时promise的状态是fulfilled,所以会进入.then()并不会进入.catch(),所以.catch()里面的代码不会执行,由于.then()是异步代码切是微任务,丢进异步队列

        5.继续往下走执行console.log('script--end'),所以地五个打印的是'script--end',同步代码执行完毕

        6.执行异步代码,先执行微任务再执行宏任务,第3步异步队列丢进去的微任务先执行,所以第六个打印的是'async1--end',再执行第4步丢进去的微任务.then(),第七个打印的是'promise--2',最后微任务执行完毕,执行宏任务setTimeout,第八个打印的是'setTimeout'

所以最终的打印顺序是:

'script--start'

'async1--start'

'async2--'

'promise--1'

'script--end'

'async1--end'

'promise--2'

'setTimeout'

总结

        由于js是单线程,所以先执行同步代码再执行异步代码,由于event loop机制,微任务是在DOM渲染前触发,宏任务是在DOM渲染后触发,所以异步代码中先执行微任务(.then(),async/await)(ES6规范) 再执行宏任务(setTimeout,setInterval,Ajax,DOM事件)(W3C规范) 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值