事件循环
先来看一道题:
async function foo() {
console.log('foo')
}
async function bar() {
console.log('bar start')
await foo()
console.log('bar end')
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
}, 0)
bar();
new Promise(function (resolve) {
console.log('promise executor')
resolve();
}).then(function () {
console.log('promise then')
})
console.log('script end')
等同于
function bar() {
console.log('bar start')//同步代码中的宏任务
new Promise(function(resolve){
console.log('foo')//同步代码中的宏任务
resolve()
}).then(function(){
console.log('bar end')//微任务
})
}
console.log('script start')//同步代码中的宏任务
setTimeout(function () {
console.log('setTimeout')//宏任务
}, 0)
bar();
new Promise(function (resolve) {
console.log('promise executor')//同步代码中的宏任务
resolve();
}).then(function () {
console.log('promise then')//微任务
})
console.log('script end')//同步代码中的宏任务
结果:
- 先执行同步代码(宏任务),输出:
script start
bar start
foo
promise executor
script end
- 再执行微任务,输出:
bar end
promise then
- 执行当前队列所有微任务后,再执行宏任务,输出:
setTimeout
事件循环,如下图所示

js 异步执行的运行机制
1、所有任务都在主线程上执行,形成一个执行栈。
2、主线程之外,还存在一个"任务队列",只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
3、异步任务分为宏任务和微任务。
执行流程 (宏任务 > 所有微任务 > 宏任务)
1、先执行 “执行栈”中同步任务(同步任务属于宏任务)完成,读取“任务队列”,执行有了结果的异步任务,进入执行栈并开始执行,
2、先执行完本次宏任务中的所有微任务
3、再执行下一个宏任务
4、再执行本宏任务中所有的微任务。
然后继续步骤3
setTimeout(() => {
console.log('异步中宏任务1')
new Promise(function (resolve) {
resolve();
}).then(function () {
console.log('宏任务1中的微任务1')
}).then(function () {
console.log('宏任务1中的微任务2')
})
}, 0);
setTimeout(() => {
console.log('异步中宏任务2')
new Promise(function (resolve) {
resolve();
}).then(function () {
console.log('宏任务2中的微任务1')
}).then(function () {
console.log('宏任务2中的微任务2')
})
}, 0);
setTimeout(() => {
console.log('异步中宏任务3')
new Promise(function (resolve) {
resolve();
}).then(function () {
console.log('宏任务3中的微任务1')
}).then(function () {
console.log('宏任务3中的微任务2')
})
}, 0);