每个线程都有自己的事件循环,
每个web woker都有自己的事件循环,所以他可以独立循环,
同一个origin的所有窗口共享一个事件循环,所以他们可以同步通信。
Microtask 微任务
微任务通常被安排用于在当前执行脚本之后立即发生的事情,比如对操作做出反应,或者用于异步。
微任务队列在每次任务结束(栈清空)时处理。
在处理微任务期间,所有微任务都会被处理,直到清空。
微任务包括:nextTick,mutation observer callbacks,promise callbacks
nextTick优先级高于其他微任务,先执行完所有nextTick(),才执行其他微任务
Task按顺序执行,浏览器可以在任务之间进行渲染。Microtask按顺序执行:- 在每次回调之后,没有其他
JavaScript处于中间执行状态的时候。 - 在每个
Task任务结束时
- 在每次回调之后,没有其他
示例1
console.log('script start');
setTimeout(function () {
console.log('setTimeout');
}, 0);
Promise.resolve()
.then(function () {
console.log('promise1');
})
.then(function () {
console.log('promise2');
});
console.log('script end');
结果:
script start
script end
promise1
promise2
setTimeout
示例2: 点击inner
<div class="outer">
<div class="inner"></div>
</div>
// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');
// Let's listen for attribute changes on the
// outer element
new MutationObserver(function () {
console.log('mutate');
}).observe(outer, {
attributes: true,
});
// Here's a click listener…
function onClick() {
console.log('click');
setTimeout(function () {
console.log('timeout');
}, 0);
Promise.resolve().then(function () {
console.log('promise');
});
outer.setAttribute('data-random', Math.random());
}
// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);
点击inner后结果:
click
promise
mutate
click
promise
mutate
timeout
timeout
示例3: 在上述代码后面加入一行
inner.click();
与示例2的区别是,2是手动点击,3是js触发
输出结果:
click
click
promise
mutate
promise
timeout
timeout
其余补充
- timers: 这个阶段执行
setTimeout()和setInterval()设定的回调。 - pending callbacks: 上一轮循环中有少数的
I/O callback会被延迟到这一轮的这一阶段执行。 - idle, prepare: 仅内部使用。
- poll: 执行
I/O callback,在适当的条件下会阻塞在这个阶段 - check: 执行
setImmediate()设定的回调。 - close callbacks: 执行比如
socket.on('close', ...)的回调。
每个阶段执行完毕后,都会执行所有微任务(先 nextTick,后其它),然后再进入下一个阶段。