事件循环promise的async和await的执行

本文详细解析了JavaScript中的事件循环机制,重点讨论了同步任务和异步任务的区别,以及微任务和宏任务的执行顺序。通过示例代码,阐述了async函数中await关键字的工作原理,指出await后的表达式如果是Promise,其后的代码会被注册为微任务,待当前执行上下文结束后执行。文章还区分了await后直接跟变量和跟异步函数调用两种情况的执行差异,并分析了新版打印结果的变化。
摘要由CSDN通过智能技术生成

首先 事件循环 是分为同步任务异步任务,同步任务在浏览器主线程上执行,等同步任务执行完之后再去查看宏任务队列和微任务队列,微任务的优先级比宏任务高,因此先执行微任务队列里面的任务;而promise的async和await就属于微任务。

先看一个小例子:

console.log('script start')
 
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1()
 
setTimeout(function() {
console.log('setTimeout')
}, 0)
 
new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})
 
console.log('script end')
 // 旧版输出如下,但是请继续看完本文下面的注意那里,新版有改动
 /**
  script start 
  async2 end 
  Promise
  script end 
  promise1 
  promise2 
  async1 end 
  setTimeout
 */
 

我们知道async隐式返回 Promise 作为结果的函数,那么可以简单理解为,await后面的函数执行完毕时,await会产生一个微任务(Promise.then是微任务)。但是我们要注意这个微任务产生的时机,它是执行完await之后,直接跳出async函数,执行其他代码(此处就是协程的运作,A暂停执行,控制权交给B)。其他代码执行完毕后,再回到async函数去执行剩下的代码,然后把await后面的代码注册到微任务队列当中

新版的打印是这样的

// script start => async2 end => Promise => script end => async1 end => promise1 => promise2 => setTimeout

我们可以分2种情况来理解:

1、如果await 后面直接跟的为一个变量,比如:await 1;这种情况的话相当于直接把await后面的代码注册为一个微任务,可以简单理解为promise.then(await下面的代码(console.log(‘async1 end’)))。然后跳出async1函数,执行其他代码,当遇到promise函数的时候,会注册promise.then()函数到微任务队列,注意此时微任务队列里面已经存在await后面的微任务。所以这种情况会先执行await后面的代码(async1 end),再执行async1函数后面注册的微任务代码(promise1,promise2)。

2、如果await后面跟的是一个异步函数的调用,比如上面的代码,将代码改成这样:

console.log('script start')
 
async function async1() {
    await async2()
    console.log('async1 end')
}
async function async2() {
    console.log('async2 end')
    return Promise.resolve().then(()=>{
        console.log('async2 end1')
    })
}
async1()
 
setTimeout(function() {
    console.log('setTimeout')
}, 0)
 
new Promise(resolve => {
    console.log('Promise')
    resolve()
})
.then(function() {
    console.log('promise1')
})
.then(function() {
    console.log('promise2')
})
 
console.log('script end')
/**
 script start 
 async2 end 
 Promise 
 script end 
 async2 end1 
 promise1 
 promise2
 async1 end
 setTimeout

*/

此时执行完awit并不先把await后面的代码注册到微任务队列中去,而是执行完await之后,直接跳出async1函数,执行其他代码。然后遇到promise的时候,把promise.then注册为微任务。其他代码执行完毕后,需要回到async1函数去执行剩下的代码,然后把await后面的代码注册到微任务队列当中,注意此时微任务队列中是有之前注册的微任务的。所以这种情况会先执行async1函数之外的微任务(promise1,promise2),然后才执行async1内注册的微任务(async1 end). 可以理解为,这种情况下,await 后面的代码会在本轮循环的最后被执行…

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值