如何知道入队事件在 Javascript 引擎事件队列中的大致位置?
How to know the approximate position of an enqueued event in a Javascript Engine's event queue?
假设我们有一系列事件正在生成并排队到可用的 Javascript 引擎的事件队列中。是否有一种方法或任何行业最佳实践来估计已排队的特定事件的位置?
非常感谢任何对此主题的见解。
没有以编程方式查看事件循环队列的标准方法。了解一个事件可能在该队列中的位置的唯一方法是了解它相对于其他事件的添加时间,以及了解事件循环中哪些类型的事件。
在现代环境中,JavaScript 有两种 "do this later" 排队:主事件循环(包含 "macrotasks")和末尾的第二个循环 运行由该宏任务调度的任何 "microtasks" 的每个主循环任务。在浏览器上还有第三种东西,requestAnimationFrame
(RAF),它与事件循环是分开的(但仍与它们协调)。
您熟悉的大多数事件处理程序在主事件循环中被称为 "macrotasks"。 setTimeout
、DOM 事件等
Promise 完成处理程序在它们排队的宏任务之后立即被调用为 "microtasks"(因此它们在下一个宏任务之前 运行,如果有的话,即使它首先排队)。
当浏览器即将重绘时,在宏任务之间调用 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 回调在它们之间的不同时间发生(通常在最后,但并非总是如此)。
还要注意在下一个宏任务之前如何承诺决议(微任务)运行。
假设我们有一系列事件正在生成并排队到可用的 Javascript 引擎的事件队列中。是否有一种方法或任何行业最佳实践来估计已排队的特定事件的位置?
非常感谢任何对此主题的见解。
没有以编程方式查看事件循环队列的标准方法。了解一个事件可能在该队列中的位置的唯一方法是了解它相对于其他事件的添加时间,以及了解事件循环中哪些类型的事件。
在现代环境中,JavaScript 有两种 "do this later" 排队:主事件循环(包含 "macrotasks")和末尾的第二个循环 运行由该宏任务调度的任何 "microtasks" 的每个主循环任务。在浏览器上还有第三种东西,requestAnimationFrame
(RAF),它与事件循环是分开的(但仍与它们协调)。
您熟悉的大多数事件处理程序在主事件循环中被称为 "macrotasks"。 setTimeout
、DOM 事件等
Promise 完成处理程序在它们排队的宏任务之后立即被调用为 "microtasks"(因此它们在下一个宏任务之前 运行,如果有的话,即使它首先排队)。
当浏览器即将重绘时,在宏任务之间调用 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 回调在它们之间的不同时间发生(通常在最后,但并非总是如此)。
还要注意在下一个宏任务之前如何承诺决议(微任务)运行。