搞明白这段代码的输出顺序,Js异步编程就懂了一半

执行下面这段代码,如果和你想的输出顺序一致,那么你可能已经掌握了Js的异步编程,本文对你来说或许没太大帮助。什么,输出顺序和你想的不一样?请往下看:

async function log(x){
  console.log(x)
  setTimeout(()=>{ console.log('H')},0);
  new Promise((resolve,reject)=>{
    console.log("G");
    resolve();
  }).then(()=>{
    console.log('J')
  })
  console.log('I');
}


new Promise((resolve,reject)=>{
  console.log('A');
  resolve();
}).then(()=>{
  console.log('B')
})

console.log('C');

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

log('E')
console.log('F');
debugger;
复制代码

执行代码,开始第一轮tick,首先遇到Promise

  • Promise构造函数内部属于宏任务,立即执行,输出A,然后resolve().then()的回调会加入此轮tick尾部
  • 输出C
  • 遇到定时器,0秒后将回调函数内的操作加入下一轮tick
  • 执行async函数log()
    • 输出E
    • 遇到定时器,0秒后将回调函数内的操作加入下一轮tick
    • 遇到Promise,输出G,.then()的回调会加入此轮tick尾部
    • 输出I
  • 输出F
  • 第一轮tick结束,执行tick尾部的微任务
    • 输出B
    • 输出J
  • 开始第二轮tick
  • 输出D
  • 输出H
  • 事件队列为空,运行完毕

另外,如果async函数内部出现await,那么执行情况是怎样的呢?我们来在async函数中await一个Promise,代码如下:

async function log(x){
  console.log(x)
  setTimeout(()=>{ console.log('H')},0);
  new Promise((resolve,reject)=>{
    console.log("G");
    resolve();
  }).then(()=>{
    console.log('J')
  })
  
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  await new Promise((resolve,reject)=>{
    console.log('await 1');
    resolve()
  }).then(()=>{
    console.log('await 2');
  })
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  console.log('I');
}

复制代码

你如果执行下代码,会发现在插入await之后,执行顺序发生了很大变化:

  • 第一轮tick
  • 执行async函数log()之前的顺序没有改变。输出A、输出C,且B加入此轮tick尾部,D加入下一轮tick
  • 执行async函数log()
    • 输出E
    • 遇到定时器,0秒后将回调函数内的操作加入下一轮tick
    • 遇到Promise,输出G,.then()的回调会加入此轮tick尾部
    • 此时,就到了await的手中,嘿嘿,不过await的是Promise构造器,输出await 1

await会将当前async函数的执行权交出,等待Promise的状态改变后,再继续执行,并且await返回的是一个Promise。所以我理解为await之后的代码加入了此轮tick尾部(执行验证发现,确实是这样)。

  • 输出F
  • 第一轮tick结束,输出tick
    • 输出B
    • 输出J
    • 输出await 2
    • 输出I
  • 第二轮tick开始
    • 输出D
    • 输出H
  • 事件队列为空,运行完毕

转载于:https://juejin.im/post/5ce778886fb9a07ef7104de5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值