看看下面这道题,你才结果是什么?
大佬不用看了,小白可以了解一下
/
/
/
结果是 3,2,1,1,2,3
我们先加上几个时间戳,方便思考,下面有解析哦。
这是打印
以下只是在下的愚见,有错误希望大家友好指出
可以看到,时间戳走到上面的循环中,先输出了三次循环,然后输出了下面这个循环的第一次。因为先从上往下走,走到foreach内部第一个循环时,发现是一个async函数,执行它,走到它的内部,new Promise会立即执行,然后触发一次'C'+时间,并且抛出宏任务定时器,然后把console.log(ret,Date.now())丢到.then()中执行,(这是因为async/await是promise的语法糖,转成promise好理解)也就是定时器变成resolve时执行。然后三次循环,每次分别都是async函数((await(定时器)).then(后面的语句,但是在这个async函数内))。
执行完三次,这时第一个循环中定时器还没到时间,走到下面的循环,循环第一次,遇到await执行内部,遇到Promise执行内部,输出console.log('A' + Date.now())这时其实就用了一毫秒左右,然后遇到定时器,抛出,等待定时器回调resolve(),把后面的语句放入.then()执行,这就是区别所在。
这里的结构是——外部async(上面的循环,下面的循环第一次await(第一个定时器).then(第一个定时器resolve()打印第一个循环数值,还有下面的两次循环,第二次循环开始await(第二个定时器).then(打印第二次数值,第三次循环await(第三个定时器).then(打印第三次循环数值))))
群里老哥给的解释可能比我说的还清楚
@骑蚂蚁看星星
async函数遇到await就把上下文还给外层函数,然后等右边的promise完成之后再拿回上下文, 因为foreach的参数是一个完整的async函数,所以foreach不会阻塞。
Event Loop 执行顺序如下所示:
首先执行同步代码,这属于宏任务
当执行完所有同步代码后,执行栈为空,查询是否有异步代码需要执行
执行所有微任务
当执行完所有微任务后,如有必要会渲染页面
然后开始下一轮 Event Loop,执行宏任务中的异步代码,也就是 setTimeout 中的回调函数