假设我们有一系列事件正在生成并被排入可用的 Javascript 引擎的事件队列中。是否有一种方法或任何行业最佳实践来估计特定事件的排队位置?
非常感谢您对此主题的任何见解。
假设我们有一系列事件正在生成并被排入可用的 Javascript 引擎的事件队列中。是否有一种方法或任何行业最佳实践来估计特定事件的排队位置?
非常感谢您对此主题的任何见解。
没有以编程方式查看事件循环队列的标准方法。知道一个事件可能在该队列中的位置的唯一方法是知道它是何时相对于其他事件添加的,以及知道什么类型的事件在事件循环中的位置。
在现代环境中,JavaScript 有两种“稍后再做”队列:主事件循环(包含“宏任务”),以及在每个主循环任务结束时为该宏任务调度的任何“微任务”运行的第二个循环。在浏览器上还有第三件事,requestAnimationFrame
(RAF),它与事件循环分开(同时仍与它们协调)。
您熟悉的大多数事件处理程序在主事件循环中称为“宏任务”。setTimeout
, DOM 事件等。
Promise 完成处理程序在它们排队的宏任务之后立即被称为“微任务”(因此它们在下一个宏任务之前运行,如果有的话,即使它首先排队)。
当浏览器即将重绘时,宏任务之间会调用 RAF 回调,即使下一个宏任务在requestAnimationFrame
回调之前排队也是如此。
例子:
function run() {
requestAnimationFrame(function() {
log("RAF 1");
});
function log(msg) {
var p = document.createElement("pre");
p.appendChild(document.createTextNode(msg));
document.body.appendChild(p);
}
setTimeout(function() {
log("timeout 1");
Promise.resolve().then(function() {
log("resolution 2 -- before timeout 2");
});
}, 0);
setTimeout(function() {
log("timeout 2");
requestAnimationFrame(function() {
log("RAF 2");
});
}, 0);
setTimeout(function() {
log("timeout 3");
requestAnimationFrame(function() {
log("RAF 3");
});
}, 0);
Promise.resolve().then(function() {
log("resolution 1");
});
}
function tick() {
document.body.innerHTML = "";
run();
setTimeout(tick, Math.random() * 800);
}
tick();
pre {
margin-top: 0;
margin-bottom: 0;
}
如果你看够长的时间,你会注意到虽然超时和承诺解决总是以相同的顺序,但 RAF 回调发生在它们之间的不同时间(通常在最后,但不总是)。
还要注意承诺解决方案(微任务)如何在下一个宏任务之前运行。