赞
踩
题目:
async function async1() { console.log(1); await async2() console.log(2); } async function async2() { console.log(3); } console.log(4); setTimeout(function () { console.log(5); }, 0) async1(); new Promise(function (resolve) { console.log(6); resolve(); }).then(function () { console.log(7); }) console.log(8);
请先思考你认为其打印的结果,答案在下方的刮刮乐中…
答案:4 1 3 6 8 2 7 5← 刮刮乐,Just 刮 it!
先讲几个关键点:
题目中有一个定时器函数,然而我们将定时器的等待时间设置为了0,有的同学可能就有疑问了,这个定时器会不会立即执行?
众所周知,定时器函数是异步操作。
即便我们将定时器的等待时间设置为0,它也不可能真正做到等待0毫秒就立即执行,所以还是会先去执行下面的同步操作。
且 定时器函数在所有异步操作中总是最后执行,即它的优先级最低。
我们说Promise是异步的,指的是Promise的 then() 和 catch() 方法是异步的,在 new 一个 Promise对象 的时候是同步的!
async函数同理,如果async函数中没有await关键字,那么这个async函数执行起来和普通函数没有什么区别。
await 关键字并非只是等待一个值可用那么简单,JavaScript运行时,在碰到await关键字时,会记录在哪里暂停执行,等到 await 右边的值可用了,JavaScript运行时会向消息队列中推送一个任务,这个任务会恢复异步函数的执行。
因此,即使await后面跟着一个立即可用的值,函数的其余部分也会被异步求值, 即会先执行函数后面的同步操作。 (定时器函数和这个同理)下面的例子演示了这一点:
async function foo() {
console.log(2);
await null;
console.log(4);
}
console.log(1);
foo();
console.log(3);
// 1
// 2
// 3
// 4
了解以上几点后,我们来具体分析一下执行步骤:
第一个打印的肯定是 4
,这个应该没什么争议吧;
然后代码执行到定时器函数,定时器函数是异步操作,先挂起,继续执行同步操作;
所以代码又执行到了 async1 函数,控制台打印输出了 1
。
然后碰到了await关键字,JavaScript记录在这里暂停执行,然后去执行 await 后的函数,所以控制台打印了 async2 里的 3
。
async2 函数执行完毕后,JavaScript会向消息队列中推送一个任务,这个任务会恢复异步函数的执行。
但是,当前的执行线程中已经排列着其他同步操作,所以要先执行同步操作才能恢复异步函数的执行。上面的定时器函数也是同理。
即先执行 new Promise对象 时的 console.log( 6
) 及代码末尾的 console.log( 8
)
同步操作执行完毕后,又跳回到 async1 函数,恢复异步函数的执行,控制台输出2
然后 then() 方法和定时器函数都是异步操作,但是定时器函数的优先级最低,所以会先打印 then() 中的7
最后恢复定时器函数的执行,控制台打印5
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。