gpt4 book ai didi

javascript - 'click' 之类的事件是宏任务吗?

转载 作者:行者123 更新时间:2023-12-04 00:50:26 26 4
gpt4 key购买 nike

代码:

setTimeout(() => console.log(1), 10);
for (let i = 0; i < 3e9; i++) {}
console.log(0);
window.onclick = () => console.log('click');

当这个脚本运行时:

  • 如果我在第 2 行的同步代码运行时没有“点击”,控制台会显示预期结果:

    0
    1
  • 如果我在第 2 行上的同步代码运行时“单击”控制台显示意外结果:

    0
    click
    1

所以我有两个问题:

  1. 如果“点击”是一个宏任务,那么它应该在 setTimeout 之后进入宏任务回调队列吗?这样当同步代码结束时,栈为空,macrotask回调队列将console.log(0)入栈,栈执行,然后回调队列将console.log('click')入栈,栈执行。<
  2. 如果我在第 2 行的同步代码运行时单击,为什么我在控制台中看到“单击”?我在执行者到达第 4 行之前点击了...

最佳答案

有各种task-queues ,它们都有不同的优先级,由用户代理 (UA) 设置。

Event Loop's processing model的第一步是从这些任务队列中的任何一个中选择一个任务,在那里他们可以决定即使一个任务实际上已经排在另一个任务之后,他们也可以选择它,只要他们没有在同一个任务上排队-排队。

timer task source通常是优先级较低的项目之一,而 UI task source最优先考虑的问题之一。

这就是您在这里遇到的情况。

请注意,有一个 API 提案允许我们的网络开发人员访问此优先级系统:https://github.com/WICG/main-thread-scheduling/blob/master/PrioritizedPostTask.md

setTimeout(() => console.log("timeout"), 0);

if( window.scheduler ) { // try to use the Prioritized postTask API
scheduler.postTask(() => console.log("low priority task"), { priority: "background" });
scheduler.postTask(() => console.log("normal priority task"), { priority: "user-visible" });
scheduler.postTask(() => console.log("high priority task"), { priority: "user-blocking" });
}
else {
console.log( "The Prioritized postTask API can be enabled from chrome://flags/#enable-experimental-web-platform-features" );
}

// queue on the message task-source (faster than timeout)
const { port1, port2 } = new MessageChannel();
port1.onmessage = () => console.log("message");
port2.postMessage("");

// block for 3 full seconds
const start = performance.now();
while( performance.now() - start < 3000 ) {}
console.log(0);

在 Chrome 中使用 chrome://flags/#enable-experimental-web-platform-features设置标志,这导致

0
high priority task
normal priority task
message
timeout
low priority task

老实说,任务优先级排序可能不是消息事件和“正常”任务在我的代码段中的“超时”之前触发的原因。 timer-initialisation-steps algorithm实际上它本身是异步的,并要求 UA 在 in parallel 时将该任务排队。 (第 14 步)。所以这个任务应该无论如何都排在同步排队的其他任务之后。

还请注意,大多数 UA (至少 Chromium 和 Firefox) 都有一个饥饿系统,避免一个队列吃掉所有资源而不让其他队列执行它们的任务。


此外,为了回答问题的标题,事件不是任务,您可以很好地从同一任务同步触发事件(例如使用 EventTarget.dispatchEvent )。


对于第二个项目符号问题,

"If I click when synchronous code from line 2 is running, why I see 'click' in console at all? I clicked before executor reached the line 4..."

这仅仅是因为 UA 将继续执行 JavaScript 作业,直到它结束,甚至在 排队任务 之前,该任务会将事件分派(dispatch)给它的所有目标并最终调用它们的所有回调。所以在那个时候,你的事件处理程序已经定义好了,它的回调也是如此。

关于javascript - 'click' 之类的事件是宏任务吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66978060/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com