今天再来看看 JavaScript 的执行顺序
下面是例子:
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");
这是一道很经典的面试题,里面涉及了 宏任务,微任务,await/async ,浏览器的事件循环机制(event loop)
上一篇:https://blog.csdn.net/qq_41934908/article/details/89041097
简单理解了一下上面的这些概念
接下来我们需要知道: await/async 这是个什么东西
ECMAScript 是这样规定的 await 必须要出现在 async 函数中, 而 async 的主要作用是将函数的返回值封装为一个 Promise 对象,若函数不存在返回值的, 则得到的结果会是 Promise(undefined),总是 async 函数总会返回一个 Promise 对象。 而当代码在遇到 await 的时候,该函数内其后面的代码始终会被阻塞,await 的返回值可以是一个 Promise 对象,也可以是一个非 Promise 对象, 若是前者 Promise 会将被阻塞的代码分装成为一个异步任务,否则后面被阻塞的会被当成同步代码执行
下面开始就题论题:
代码开始执行:
console.log(“script start”)
输出 script start
执行 setTimeout 异步任务,推入 event table , 0 秒时候(满足条件)推入 event queue,等待被执行
执行 async1();
console.log(“async1 start”); 宏任务 输出 async1 start
遇到 await 之后, 后面的 console.log(“async1 end”) 会先被阻塞,去执行 async2();
async2()执行: console.log(“async2”); 同步任务 输出 async2
但是async2() 会返回一个 Promise 对象, 所以 Promise 会将 console.log(“async1 end”); 封装为异步任务,推入 event table ,满足条件后被推入 event queue,等待被执行
接下来执行 new Promise :
console.log(“promise1”); 宏任务 输出 promise1
注意后面的 then 方法属于微任务, 所以不会被立即执行,会等到该轮的所有宏任务之心完毕之后才会被执行
接下来执行最后一行宏任务:
console.log(“script end”); 输出 script end
到这个时候主线程的宏任务执行完毕,所以引擎会去监测微任务队列中是否存在需要执行的任务
console.log(“promise2”) 得到了执行,输出 promise2
微任务执行完毕之后,监测 event queue
执行 console.log(“async1 end”); 输出 async1 end
最后执行 setTimeout 并输出 settimeout
最后的执行顺序出来了:
script start
async1 start
async2
promise1
script end
promise2
async1 end
settimeout
如果觉得不是很清晰,请移步: https://juejin.im/post/5c0dcf70518825765548502b
如果有错的话,会更改后继续发布