事件回调中的事件监听器的优先级在哪里?
Where in terms of priority are eventlisteners in the event callback?
所以在这个 post 中,宏任务队列似乎包括 movemouse。但是然后使用此代码
<html>
<body>
<button id="but_one" onclick='button_one()'>Button 1</button>
<button id="but_two" onclick='button_two()'>Button 2</button>
</body>
<script>
//document.addEventListener('mousemove', e => console.log("mouse move"));
function button_one() {
console.log("button one")
}
function button_two() {
console.log("button two before")
setTimeout(() => console.log("timeout : before sleep"), 0)
autoResolve().then(msg => console.log(".then before sleep " + msg));
sleep(5000);
autoResolve().then(msg => {
sleep(2000);
console.log(".then after sleep " + msg)
});
setTimeout(() => console.log("timeout : after sleep"), 0)
console.log("button two after")
}
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
async function autoResolve() { return "resolved" }
</script>
</html>
如果您点击按钮 2,然后点击按钮 1,您可以看到两个承诺(微任务)都在按钮 1 的点击被注册之前执行,这对我来说很有意义。然而,两个超时(宏任务)似乎都发生在之后,甚至是在我单击之前排队的那个。这对我来说表明听众有它自己的第三个队列,但没有消息来源这么说。
在记录 mousemove 时观察到同样的情况,但是出于代码片段中控制台的目的,我删除了它。
为什么会这样?
编辑:所以这是在 Chrome 版本 83.0.4103.61 中完成的 Windows 10 PC
规范说事件循环可以有多个任务队列。这是 processing model 的第 1 步:
- Let taskQueue be one of the event loop's task queues, chosen in an implementation-defined manner, with the constraint that the chosen task queue must contain at least one runnable task. If there is no such task queue, then jump to the microtasks step below.
(我的重点)
浏览器可能(概念上)将事件和计时器放在单独的任务队列中,以便使事件优先于计时器回调,这并不奇怪,尤其是当该事件因 JavaScript 线程而被延迟时太忙没时间处理。
我不认为它被指定更多......呃......具体比 "implementation-defined manner." 我得到你描述的行为(定时器回调之前的 "button one" 事件) Chrome,我在事件发生前用 Firefox 获得了定时器回调。
运行 的宏任务来自多个所谓的任务源。浏览器可以自由决定以什么顺序为它们提供服务,使用多个队列,只要每个源的事件按顺序发生即可。事件侦听器和超时是不同的来源,显然您的浏览器认为点击事件更重要。
所以在这个 post 中,宏任务队列似乎包括 movemouse。但是然后使用此代码
<html>
<body>
<button id="but_one" onclick='button_one()'>Button 1</button>
<button id="but_two" onclick='button_two()'>Button 2</button>
</body>
<script>
//document.addEventListener('mousemove', e => console.log("mouse move"));
function button_one() {
console.log("button one")
}
function button_two() {
console.log("button two before")
setTimeout(() => console.log("timeout : before sleep"), 0)
autoResolve().then(msg => console.log(".then before sleep " + msg));
sleep(5000);
autoResolve().then(msg => {
sleep(2000);
console.log(".then after sleep " + msg)
});
setTimeout(() => console.log("timeout : after sleep"), 0)
console.log("button two after")
}
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
async function autoResolve() { return "resolved" }
</script>
</html>
如果您点击按钮 2,然后点击按钮 1,您可以看到两个承诺(微任务)都在按钮 1 的点击被注册之前执行,这对我来说很有意义。然而,两个超时(宏任务)似乎都发生在之后,甚至是在我单击之前排队的那个。这对我来说表明听众有它自己的第三个队列,但没有消息来源这么说。
在记录 mousemove 时观察到同样的情况,但是出于代码片段中控制台的目的,我删除了它。
为什么会这样?
编辑:所以这是在 Chrome 版本 83.0.4103.61 中完成的 Windows 10 PC
规范说事件循环可以有多个任务队列。这是 processing model 的第 1 步:
- Let taskQueue be one of the event loop's task queues, chosen in an implementation-defined manner, with the constraint that the chosen task queue must contain at least one runnable task. If there is no such task queue, then jump to the microtasks step below.
(我的重点)
浏览器可能(概念上)将事件和计时器放在单独的任务队列中,以便使事件优先于计时器回调,这并不奇怪,尤其是当该事件因 JavaScript 线程而被延迟时太忙没时间处理。
我不认为它被指定更多......呃......具体比 "implementation-defined manner." 我得到你描述的行为(定时器回调之前的 "button one" 事件) Chrome,我在事件发生前用 Firefox 获得了定时器回调。
运行 的宏任务来自多个所谓的任务源。浏览器可以自由决定以什么顺序为它们提供服务,使用多个队列,只要每个源的事件按顺序发生即可。事件侦听器和超时是不同的来源,显然您的浏览器认为点击事件更重要。