前言
上一篇介绍了 事件循环 的基础, 这一篇主要介绍 macrotask
和 microtask
。
一、引入
(function test() {
setTimeout(function() {console.log(4)}, 0);
new Promise(function executor(resolve) {
console.log(1);
for( var i=0 ; i<10000 ; i++ ) {
i == 9999 && resolve();
}
console.log(2);
}).then(function() {
console.log(5);
});
console.log(3);
})()
执行结果
1
2
3
5
4
可以看看whatwg规范,大概可以用下面的事件执行模型来理解
二、event-loop 执行模型
1.在 macrotask 队列中执行最早的那个 task ,然后移出
2.执行 microtask 队列中所有可用的任务,然后移出
3.执行下一个 macrotask 中的任务 (再跳到第2步)
三、macrotask microtask分类
macrotask: 整段script代码 setTimeout setInterval setImmediate I/O UI渲染
microtask: Promise process.nextTick Object.observe MutationObserver
按照上面的事件执行模型和事件分类,来理解一下上面的demo
//伪代码
var macrotasks = ['整段script代码'],
microtasks = [];
//一次事件循环
while( macrotasks.length>0){
macrotasks.shift();
// 有些macrotask 可能会产生macrotask microtasks
// 即 microtasks.push()
// 如上面的 '整段代码' 产生一个macrotask -> setTimeout,又产生一个microtask -> Promise
while(microtasks.length>0){
microtasks.shift();
}
}
上面的demo执行过程如下:开始时 macrotask队列 有 ‘整段的script代码’,microtask队列无任务。
开始执行第一个 macrotask:
- 1.发现
setTimeout
,执行macrotasks.push("setTimeout")
- 2.发现
Promise
,执行console.log(1)
,执行microtasks.push('Promise')
,执行console.log(2)
- 3.执行
console.log(3)
;
至此 第一个 macrotask 处理完成,检查是否有 microtask,开始处理 microtask:
- 1.执行
console.log(5)
;
至此 microtask 处理完成,检查是否还有 macrotask,开始处理第二个 macrotask:
- 1.执行
console.log(4)
四、参考文章
1.深入理解 JavaScript 事件循环(二)— task and microtask
3.理解 js 事件循环二 (macrotask 和 microtask)
4.whatwg规范