async/await以及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(function() {
  console.log('setTimeout')
}, 0)

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

console.log('script end')

关于上述这道题除了要考虑同步异步的问题,还涉及到js中的微任务和宏任务,就这道题我说一下关于我的理解。

同步和异步任务分别进入不同的执行"场所",同步的任务进入主线程,异步的进入Event Table并注册函数。当异步函数完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。上述过程会不断重复,也就是常说的Event Loop(事件循环)。

除此之外,在js中还存在宏任务和微任务。

js中的宏任务一般是:包括整体代码script,setTimeout,setInterval。

微任务是:Promise,process.nextTick。

说一下我对于async/await的理解:

1.async做了一件什么事情?

async将你的函数返回值转换为promise对象,不需要显式地返回promise对象,async关键字自动将函数的返回值变为promise对象。

2.await的作用

await关键字只能在带有async关键字的函数内部使用,在外部使用时会报错。await等待的是右侧的[表达式结果],如果右侧是一个函数,等待的是右侧函数的返回值,如果右侧的表达式不是函数则直接是右侧的表达式。await在等待时会让出线程阻塞后面的执行。await的执行顺序为从右到左,会阻塞后面的代码执行,但并不是直接阻塞await的表达式。

await之后如果不是promise,await会阻塞后面的代码,会先执行async外面的同步代码,等外面的同步代码执行完成在执行async中的代码。

如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。

一段代码执行时,会先执行宏任务中的同步代码:

  • 如果执行中遇到 setTimeout 之类宏任务,那么就把这个 setTimeout 内部的函数推入「宏任务的队列」中,下一轮宏任务执行时调用。

  • 如果执行中遇到 promise.then() 之类的微任务,就会推入到「当前宏任务的微任务队列」中,在本轮宏任务的同步代码执行都完成后,依次执行所有的微任务1、2、3。

上述这道题的执行顺序为:

第一个宏任务:

console.log('script start')

第一个宏任务中的第一个微任务:

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

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

在第一个微任务中存在await关键字,因此先输出

async1 start

接着输出

async2

await阻塞后面的代码执行,因此跳出async函数执行下一个微任务

第一个宏任务中的第二个微任务:

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

先输出:

promise1

碰到promise.then这个微任务会先执行本轮宏任务的同步代码再执行微任务

接着输出:

script end

再挨个执行所有的微任务,依次输出:

promise2
async1 end

第一个宏任务执行完成,执行第二个宏任务:

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

输出结果为:

setTimeout

这就是这道题的解题思路。

  • 9
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值