事件循环
事件循环(
Event loop)即循环去处理宏任务和微任务这些异步任务
浏览器中的Event loop
- 首先执行
script任务,这是全局任务,属于宏任务; - 宏任务执行完毕,开始执行所有的微任务;
- 微任务执行完毕,再取任务队列中的一个宏任务执行。
console.log(0);
setTimeout(function() {
console.log(1);
}, 0);
Promise.resolve().then(function() {
console.log(2);
});
console.log(3);
执行上述代码
- 首先执行
script全局宏任务,输出0,3 - 全局宏任务执行完,开始判断是否有微任务,存在微任务
Promise,开始执行,输出2 - 微任务执行完,微任务队列清空,重新渲染,之后再次判断任务队列是否有任务
- 任务队列中存在
setTimeout宏任务,开始执行,输出1
这就是一个完整的过程
一个Event loop有一个或多个任务队列,每一个Event loop只有一个微任务队列
执行JavaScript代码具体流程
- 执行全局
Script同步代码,这些同步代码有一些是同步语句,有一些是异步语句; - 全局
Script代码执行完毕后,调用栈Stack会清空; - 从微队列
microtask queue中取出位于队首的回调任务,放入调用栈Stack中执行,执行完成后microtask queue长度减1; - 继续取出队首的任务,放入调用栈
Stack中执行,以此类推,直到把microtask queue中的所有任务都执行完毕。如果在执行microtask的过程中,又产生了microtask,那么会加入到队列的末尾,也会在这个周期被调用执行; microtask queue中的所有任务都执行完毕,此时microtask queue为空队列,调用栈Stack也为空;- 取出宏队列
macrotask queue中位于队首的任务,放入Stack中执行; - 执行完毕后,调用栈
Stack为空; - 重复3-7步骤......
- 宏队列
macrotask一次只从队列中取出一个任务执行,执行完后就去执行微任务队列中的任务 - 微任务队列中所有的任务都会被依次取出来执行,直到
microtask queue为空
JS中的异步任务
1. 宏任务
script(全局任务)setTimeoutsetIntervalsetImmediateI/OUI rendering
2. 微任务
process.nextTickPromiseObject.observerMutationObserver
console.log(1);
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3)
});
});
new Promise((resolve, reject) => {
console.log(4)
resolve(5)
}).then((data) => {
console.log(data);
})
setTimeout(() => {
console.log(6);
})
console.log(7);
打印结果 1475236