gpt4 book ai didi

javascript - JS事件队列中的事件顺序

转载 作者:搜寻专家 更新时间:2023-11-01 04:29:58 25 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Is JavaScript guaranteed to be single-threaded?

(13 个答案)


6年前关闭。




事情(我相信)明白

尽管现代浏览器是多线程的,但 JavaScript 是单线程执行的,并且保证同步执行。这意味着如果进入调用堆栈,JS 会不间断地运行,直到调用堆栈再次变空。特别是,保证没有两个 JS 脚本同时运行。

然而,JavaScript 是事件驱动的。根据description of the concurrency model at MDN浏览器维护一个事件队列。如果空闲,浏览器从队列中获取第一个事件并执行相关联的 JS(如果有)。脚本终止后,浏览器再次获得控制权并继续执行下一个事件。执行 JS 脚本时,浏览器不会做任何其他事情,尤其是它会阻塞 UI。后者负责臭名昭著的“长期运行脚本警告”。

有一些真正的异步函数,如 setTimeout由运行时系统(又名浏览器)提供。它们可用于将新事件放入事件队列,如果事件已被触发且调用堆栈为空,则关联的回调将被放入调用堆栈。如果不使用 native 异步函数之一,开发人员无法创建他“自己的”异步函数。

话虽如此,setTimeout( someFunction, 0 )提供了一个选项,如何将长时间运行的代码分割成更小的部分,否则会触发“长时间运行的脚本警告”。如果调用堆栈变空,浏览器可以在执行下一段代码之前 catch 其他事件(如 UI)。

一个例子

为了检查我是否正确,我创建了这个 piece of code

"use strict";
for( var i = 0; i != 5; i++ ) {
confirm( 'This is #: ' + i );
setTimeout(
( function(j) {
return function() { confirm( 'This is #: ' + j ); };
} )( i+10 ),
0
);
}

预期结果

我希望警报框以正确的顺序出现:0、1、2、3、4、10、11、12、13 和 14。我的想法是在每次迭代中都会发生以下两个步骤:(a)第一个确认框同步显示。 (b) 一个新事件被推到事件队列的末尾。但是,尚未调用回调而是推迟了回调,因为调用堆栈不是空的,因为循环仍在运行。

因此,我希望按照该顺序首先看到警报 0、1、2、3、4,因为这是同步循环的一部分。然后循环终止,调用堆栈变得清晰。下一个事件取自恰好是第一个异步超时的事件队列。所以我预计接下来会看到 10 个。确认对话框关闭后,调用堆栈再次变得清晰。所以我预计接下来会看到 11 个。等等。

实际结果

警报框以混合顺序显示,例如0、1、2、10、11、3、12、4、13、14。

问题

为什么警报框是混合顺序的?如果至少同步部分 (0, 1, 2, 3, 4) 被显示成 block 并且只有回调被混淆,我会接受事件队列不保证事件的顺序。但是,似乎即使是同步循环也会被中断并与异步事件交错。我认为这保证不会发生。这里发生了什么?

最佳答案

这是因为在某些浏览器(在您的情况下为 Firefox)中,传统上阻止 alert , confirm , 和 prompt函数不会停止事件队列。它们确实会停止执行当前代码,直到用户与之交互,但循环继续运行并且一些 JavaScript 事件继续触发(但不是所有事件)。

Is this a Firefox bug?



不,您的代码只是具有未定义的行为。

In the spec , 暂停是可选的:

Optionally, pause while waiting for the user to acknowledge the message.



Firefox 选择不这样做是为了改善用户体验。

另一个例子:

这是一个简单的例子,展示了调整大小事件是如何触发的。这显示了您如何无法确定事件处理程序可访问的变量不会被修改,而 alert -type 对话框打开。
(function(){
'use strict';
var resized = false;
window.addEventListener('resize', function() {
resized = true;
console.log('resizing');
});
alert('resize the window before continuing');
console.log('Resize events fired while alert open?: ' + resized);
})();

关于javascript - JS事件队列中的事件顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38678419/

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