首先说结论:
async 用来指定方法为异步方法(区别于同步方法),即只有async修饰的函数中才能出现await阻塞操作,遇到阻塞是先让CPU先执行函数外的操作,之后再回函数内部执行函数内接下来的代码。而不像同步方法那样傻傻的等待,浪费CPU资源
await阻塞,后面放异步任务,当其执行完毕后,阻塞该函数的执行,去执行函数外的代码
注意这段代码是从右边开始执行,当前台发出get请求后,await使得函数进入阻塞状态(这时候response没有赋值,因为被await阻塞了),执行函数外的代码。当get请求的数据回来后,函数继续开始执行,这时候才赋值
前端代码执行分成很多次时间循环:每一次时间循环的先后顺序是执行宏任务,微任务,渲染UI
大型宏任务,那么就把SetTimeOut内部的回调函数推入到下一个宏任务,当本轮循环全部完成后才继续下一轮的执行
then函数内部是微任务,在本回合的宏任务执行完成后执行
<script>
async function async1(){
console.log('async1 start'+new Date().getTime())
await async2()
console.log('async1 end'+new Date().getTime())
}
async function async2(){
console.log('async2'+new Date().getTime());
}
console.log('script start'+new Date().getTime())
setTimeout(()=>{
console.log("settimeout"+new Date().getTime())
},500)
async1()
new Promise(function(resolve){
console.log("promise construction"+new Date().getTime())
resolve()
}).then(function(){
console.log('then 1'+new Date().getTime())
}).then(function(){
console.log('then 2'+new Date().getTime())
})
console.log("script end"+new Date().getTime())
</script>
首先执行setTimeOut,把里面的回调函数推入到下一个宏任务,之后执行async1打印 async1 start
接下里执行async2,打印async2,当该函数执行完毕后,await使得async1阻塞转而执行函数外的代码
接下里执行Promise构造函数,打印promise construction,接下来执行then函数,由于then函数是微任务,所以要等待当前这一轮的所有的宏任务执行完成
接下来打印script end,这时候函数外的代码都执行完成了,返回函数内执行被阻塞后的代码,打印async 1
本轮所有的宏任务执行完毕,开始执行微任务,也是按照先后原则执行,所以先后打印then1 ,then2
本轮所有任务完成,开始执行下一轮的宏函数,打印settimeout
所以chrome浏览器多次输出先后顺序是
第一轮宏任务:
script start async1 start async2 promise construction script end async1 end
第一轮微任务:
then 1 then 2
第三轮宏任务:
settimeout