JS里面的微任务与宏任务
宏任务与微任务分类
宏任务和微任务是JS中异步任务的两种分类,它们与事件循环(Event Loop)有关,影响着JS的执行顺序。
宏任务(macro task)是指那些在主线程上执行的任务,它们形成一个执行栈。宏任务包括:script (整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering等。
微任务(micro task)是指那些在当前任务执行结束后立即执行的任务,它们不需要等待渲染。微任务包括:Promise.then, Object.observe, MutationObserver, process.nextTick等。
运行机制
事件循环的运行机制是这样的:
- 执行一个宏任务(栈中没有就从事件队列中获取)
- 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
- 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
- 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
- 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
通过以下的代码来测试宏任务和微任务的执行顺序:
console.log("start"); // 宏任务1,同步代码
setTimeout(() => {
console.log("setTimeout"); // 宏任务2,异步代码
}, 0);
new Promise((resolve, reject) => {
for (var i = 0; i < 5; i++) {
console.log(i); // 宏任务1,同步代码
}
resolve(); // 修改promise状态为成功
}).then(() => {
console.log("promise回调函数"); // 微任务1,异步代码
});
console.log("end"); // 宏任务1,同步代码
执行结果
start
0
1
2
3
4
end
promise回调函数
setTimeout
代码分析:
- 首先执行宏任务1,即主线程上的同步代码,输出start, 0, 1, 2, 3, 4, end
- 然后遇到setTimeout,将其加入到宏任务队列等待执行
- 然后遇到promise,立即执行,修改promise状态为成功,将其回调函数加入到微任务队列
- 宏任务1执行完毕,查看是否有微任务队列,有则执行微任务队列中的所有任务,输出promise回调函数
- 微任务执行完毕,执行下一个宏任务队列中的任务,输出setTimeout
试着分析一下下在代码的结果是什么?
console.log("start"); // 宏任务1,同步代码
setTimeout(() => {
console.log("setTimeout1"); // 宏任务2,异步代码
Promise.resolve().then(() => {
console.log("promise1"); // 微任务3,异步代码
});
}, 0);
new Promise((resolve, reject) => {
console.log("promise2"); // 宏任务1,同步代码
setTimeout(() => {
console.log("setTimeout2"); // 宏任务3,异步代码
resolve(); // 修改promise状态为成功
}, 0);
}).then(() => {
console.log("promise3"); // 微任务2,异步代码
});
console.log("end"); // 宏任务1,同步代码
上面代码运行的结果是什么呢?
经过分析以后,我们得到结果是:start, promise2, end, setTimeout1, promise1, setTimeout2, promise3
可以按照以下步骤来分析这个例子:
- 首先执行宏任务1,即主线程上的同步代码,输出start, promise2, end
- 然后遇到setTimeout,将其加入到宏任务队列等待执行
- 然后遇到promise,立即执行,但是其状态由内部的setTimeout决定,所以将其加入到宏任务队列等待执行
- 宏任务1执行完毕,查看是否有微任务队列,没有则执行下一个宏任务队列中的任务
- 执行宏任务2,即setTimeout1,输出setTimeout1,然后将其回调函数加入到微任务队列
- 宏任务2执行完毕,查看是否有微任务队列,有则执行微任务队列中的所有任务,输出promise1
- 微任务执行完毕,执行下一个宏任务队列中的任务
- 执行宏任务3,即setTimeout2,输出setTimeout2,然后修改promise状态为成功,将其回调函数加入到微任务队列
- 宏任务3执行完毕,查看是否有微任务队列,有则执行微任务队列中的所有任务,输出promise3
评论区