参考
理解 JavaScript 中的 macrotask 和 microtask
事件处理机制
先执行同步代码,再执行异步代码(回调函数)。(dom事件监听, 设置定时器, 发送ajax请求)
当事件发生时, 回调函数被添加到回调列队中。
只有当同步代码执行完后, 才会遍历读取回调队列中的回调函数执行。
setTimeout
setTimeout(fn, 0)
会立即将fn加入回调队列,直到同步代码和回调队列中前面的函数执行完,fn 才会执行。
其次,浏览器的实现会有一个最短间隔,一般在10ms以内。
所以,计时器实际上是在指定多久以后可以执行某个回调函数,而不是指定某个函数的确切执行时间。
还可以考虑操作系统切换进程的影响。
Macrotasks 和 Microtasks
microtasks: Promise,process.nextTick 等
macrotasks: setTimeout, setInterval 等
在每一次事件循环中,先将 microtasks 队列清空,macrotasks 队列只会提取一个执行,然后再去清空 microtasks 队列,如此反复。
代码示例:
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
输出顺序: "promise1" "promise2" "setTimeout"
setTimeout(function() {
console.log('setTimeout1');
Promise.resolve().then(function() {
console.log('promise3');
})
}, 0);
setTimeout(function() {
console.log('setTimeout2');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
输出顺序: "promise1" "promise2" "setTimeout1" "promise3" "setTimeout2"