promise
async/await
generator
settimeout、async、promise 混用的执行顺序
async function async1() {
console.log("2");
await async2();
console.log("7");
}
async function async2() {
console.log( '3');
}
console.log("1");
setTimeout(function () {
console.log("8");
},0);
async1();
new Promise(function (resolve) {
console.log("4");
resolve();
}).then(function () {
console.log("6");
});
console.log('5');
执行结果:
1 2 3 4 5 6 7 8
分析
await async2()
执行这一句后,输出 async2 后,await 会让出当前线程,将后面的代码加到任务队列中,然后继续执行 test() 函数后面的同步代码
执行到 setTimeout 函数时,将其回调函数加入队列(此队列与 promise 队列不是同一个队列,执行的优先级低于 promise)继续执行- 创建 promise 对象里面的代码属于同步代码,promise 的异步性体现在 then 与 catch 处,所以 promise1 被输出,然后将 then 函数的代码加入队列,继续执行同步代码,输出 script end
- 至此同步代码执行完毕,开始从队列中调取任务执行,由于刚刚提到过,setTimeout 的任务队列优先级低于 promise 队列,所以首先执行 promise 队列的第一个任务,执行 then 方法的部分,输出 promise2 ,然后执行 async1 中 await 后面的代码,输出 async1 end
- 最后 promise 队列中任务执行完毕,再执行 setTimeout 的任务队列,输出 settimeout
至此,该题的输出结果分析完毕了,这类的执行结果可以用一句话总结,先执行同步代码,遇到异步代码就先加入队列,然后按入队的顺序执行异步代码,最后执行 setTimeout 队列的代码。
补充一下队列任务优先级:promise.Trick() > promise的回调 > async > setTimeout > setImmediate
不过如果 await 后面跟着 Promise 的话,async1 end 需要等待三个 tick 才能执行到。那么其实这个性能相对来说还是略慢的,所以 V8 团队借鉴了 Node 8 中的一个 Bug,在引擎底层将三次 tick 减少到了二次 tick。也就是说v8引擎浏览器打印出来的,promise2和async1 end是相反的