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');
代码运行结果为
接下来我们一行行解释:
开始申明了async1和async2两个异步函数,在async中调用了async这个函数,但是只是申明,并没了直接调用。
所以一开始输出
script start
接下来运行到了settimeout,settimeout是一个异步宏任务,事件循环是一个宏任务-微任务的循环,整个script算是一次宏任务,所以遇到了settimeout只是将settimeout放到了宏任务的任务队列中,暂时不去处理它。
接下来调用了async1函数,一开始输出了async1 start,然后在调用了async2函数,await是一个让出线程的标志,先去执行async2函数,输出了async2,接着会跳出整个async函数执行后面的js代码,等本轮任务循环结束后再执行await后面的代码。
接下来到了promise,promise是一个对象,它的构造函数里面还是同步执行的,所以输出promise1,然后因为promise是一个异步微任务,会将返回的结果也就是then或者是catch的回调加入异步微任务的任务队列中。
接着输出script end,代表本次的宏任务执行完成了。记得上面提到的await,在本次宏任务执行完成后执行,输出async1 end。
接下来,js引擎会找微任务队列,如果有微任务存在则执行读取微任务,上面说到了,promise.then里面是异步微任务的操作,所以输出promise2。
到此,一次宏任务和一次微任务已经执行结束。
接下来js引擎接着会找宏任务队列中的任务,读取settimeout这个任务,输出settimeout。
参考文献:
js浏览器事件循环