因此在此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单击之前,两个诺言(微任务)都已执行,这对我来说很有意义。但是,两个超时(宏任务)似乎都在之后发生,甚至是在我单击之前排队的一个。对我来说,这表明侦听器具有自己的第3个队列,但是没有消息来源这么说。
在记录mousemove时也观察到了同样的情况,但是出于代码控制台中控制台的目的,我删除了该记录。
为什么会这样?
编辑:因此,这是在Windows 10 PC上的Chrome版本83.0.4103.61中完成的
答案 0 :(得分:2)
该规范说事件循环可能有多个任务队列。这是processing model的第1步:
- 让 taskQueue 成为以实现定义的方式选择的事件循环任务队列之一,并限制所选任务队列必须包含至少一个可运行的任务队列任务。如果没有这样的任务队列,请跳到下面的微任务步骤。
(我的重点)
毫不奇怪,浏览器可能(从概念上来说)在单独的任务队列中具有事件和计时器,以便将事件优先于计时器回调,尤其是当该事件由于JavaScript线程太忙而无法处理而被延迟时较早。
我不认为它比“实现定义的方式”更具体。我得到了您在Chrome中描述的行为(计时器回调之前的“按钮一”事件),并且在Firefox事件发生之前得到了计时器回调。
答案 1 :(得分:2)
要运行的宏任务来自多个所谓的任务源。只要每个源的事件顺序发生,浏览器就可以使用多个队列自由决定以什么顺序为它们提供服务。事件监听器和超时是不同的来源,显然您的浏览器认为click事件更为重要。