首先咱们要知道关于JavaScript的一些规则:git
同步任务都在主线程上执行,造成一个执行栈。当主线程执行完以后,运行微任务(micro-task)队列的任务直到为空,更新UI渲染(会根据浏览器的逻辑,决定要不要立刻执行更新),而后再运行宏任务(macro-task)队列的任务直到为空......流程以下:github
(主线程上的执行栈同步任务,能够视为是第一个macro-task队列)
macro-task -> micro-task(若是存在) -> 更新UI渲染
复制代码
如此无限循环上面的流程,是为JavaScript的Event Loop机制。chrome
宏任务(macro-task),宏任务队列能够有一个或者多个。每一个任务都有一个任务源(task source),源自同一个任务源的 task 必须放到同一个任务队列,从不一样源来的则被添加到不一样队列。promise
宏任务:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering.浏览器
微任务(micro-task),微任务在渲染更新前,macro-task以后执行。 关于async和await,由于async await 自己就是promise+generator的语法糖。因此await后面的代码是microtask。实际上await是一个让出线程的标志。await后面的表达式会先执行一遍,将await后面的代码加入到microtask中,而后就会跳出整个async函数来执行后面的代码。bash
微任务:process.nextTick, Promise, Object.observer, MutationObserver,await.异步
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');
复制代码
流程以下:async
完整结果以下:函数
/**
*script start
*async1 start
*async2
*promise1
*script end
*async1 end
*promise2
*setTimeout
*/
复制代码
该结果基于chrome 版本 72.0.3626.121。由于async await标准有所改变,因此稍老版本的浏览器结果可能不一致。oop
参考以下: