最初看到macrotask和microtask是在某一篇讲Vue.$nextTick背后的机制时注意到的。
随着疑问的加深,就很有必要探究一下这两个是什么,有什么区别。
规范文档
我们先看定义:https://html.spec.whatwg.org/multipage/webappapis.html#event-loops
这里说明一下macrotask其实就是里面说的task。
macrotask和microtask是在event loops下定义的。从上面定义可以得知:
- 每个浏览器环境,至多有一个event loop。
- 每一个event loop有一个或多个task queue。一个task queue是一个有序的task列表。
- 每个event loop都有一个microtask queue。一个microtask是直接放到microtask queue里的,而不是放到task queue里。
也就是说一个event loop = task queues + microtask queue。
然后一个event loop执行任务的流程是:
- 把最早的任务(task A)放入任务队列。
- 如果 task A 为空,则直接跳转到第6步。
- 将 currently running task 设置为 task A。
- 执行 task A
- 将 currently running task 设置为 null,并移除 task A。
- 执行 microtask queue:
- a. 在 micro queue 中选出最早的任务 task X。
- b. 如果 task X 为空,直接跳转到 g
- c. 将 currently running task 设置为 task X。
- d. 执行 task X。
- e. 将 currently running task 设置为 null,并移除 task X。
- f. 跳转到 a。
- g. 结束 microtask queue。
- 跳转到第 1 步。
然后,从上面,我们可以得到这一点:
- 每个 macrotask 执行完后都会执行一下 microtask queue。
两者的具体实现:
- macrotask: setTimeout, setInterval, setImmediate, I/O, UI渲染,Event,Ajax。
- microtask:Promise, process.nextTick, Object.observe, MutationObserver。
PS:记住 microtask 有哪些就好 ;)
一道题目
我们再来看一道题目:
console.log(1);
setTimeout(function() {
console.log(2);
}, 0);
new Promise(function (resolve) {
console.log(3);
var i = 0;
while (i < 9999999) {
i++;
}
resolve();
console.log(4);
}).then(function() {
console.log(5);
});
console.log(6);
结果是怎么样呢?
1
3
4
6
5
2
注意3,4这两个,这个是直接执行的。