Javascript 在事件循环中未放置while循环期间单击

Javascript 在事件循环中未放置while循环期间单击,javascript,Javascript,我在下面,这里解释了JS引擎的事件循环将事件放置在事件队列中——只有当执行堆栈为空时,才会执行它们的处理程序。作者甚至在1:45:18展示了一个例子。代码是: 函数waitThreeSeconds(){ var ms=3000+新日期().getTime(); while(新日期()

我在下面,这里解释了JS引擎的事件循环将事件放置在事件队列中——只有当执行堆栈为空时,才会执行它们的处理程序。作者甚至在1:45:18展示了一个例子。代码是:

函数waitThreeSeconds(){ var ms=3000+新日期().getTime(); while(新日期() 当我在浏览器中运行它时,while循环按预期运行3秒钟,然后打印两条消息:

如果在while循环完成后单击任意位置,将打印一条消息“click event!”。但是,如果在while循环中单击,则不会注册单击事件。在视频中,在这两种情况下,都会注册单击

这是因为自2015年该视频首映以来JavaScript引擎发生了一些更新吗?我正在使用MS Edge浏览器

视频作者建议,尽管JS是一种单线程语言,但web浏览器以并发方式实现JS解释/引擎,其中事件与JS代码的执行分开添加到事件队列中

我的实验让我困惑,因为它表现出不同的行为。有人能解释一下原因吗

//编辑

经过进一步的实验,我发现在视频中看到的行为也可以在Chrome中找到(我猜Chrome也是如此,尽管我没有安装它)。
但是,Edge(基于铬的Edge)的行为不同,在while循环期间根本不注册单击。

while循环正在阻塞,并将阻止事件队列进行。还有一个类似的问题!一个很好的方法是用
setTimeout(function(){},3000)
setInterval(function(){},3000)
替换while循环,如果使用
while
循环,在这3秒钟内您将无法执行任何操作。相反,您需要使用timeout。这将允许您在超时运行时继续执行操作

让activeTimer=null;
函数waitThreeSeconds(){
如果(活动计时器){
log(“停止函数执行”);
clearTimeout(activeTimer);
}
log(“开始函数执行”);
activeTimer=setTimeout(函数(){
console.log('finished function');
activeTimer=null;
}, 3000);
}
函数nonBlockingClickHandler(){
log(`Click event!`);
}
document.addEventListener('click',非阻塞ClickHandler);

等待三秒钟()Web浏览器只能异步运行,技术上不能并发运行。您在这里实现的是传统上所谓的“忙等待”循环。此方法是一种阻塞算法,意味着在第一个代码完成之前,后面的代码不会执行。不过这是件好事。想象一下,如果您的代码只是无序执行,会有多混乱

如果您想利用浏览器的内置异步功能,则需要使用其中一个提供的函数来与Javascript的交互

在这种情况下,您可能希望使用使其真正异步

函数waitThreeSeconds(){ setTimeout(函数(){ log('finished function'); }, 3000); } 函数clickHandler(){ console.log('click event!') } document.addEventListener('click',clickHandler); 等待三秒钟 console.log('finished execution')

其他类似的函数有
setImmediate()
,它在堆栈为空时立即执行;以及
setInterval()
,它允许您以固定时间或延迟执行函数数次。

JavaScript不会在浏览器选项卡中同时运行,因此,无论何时运行for/while循环,线程都会被阻塞,并且它必须完成才能处理其他事件(在本例中为事件侦听器)

因此,当运行while循环时,在循环完成之前不会处理任何事件


我试着在chrome中运行,它的工作方式与两个听众在循环后被解雇的方式相同。

为什么它在视频中工作,而对你不工作?这种行为是特定于浏览器的,这是有道理的。我不认为有任何正式的标准规定在UI线程繁忙时是否接受和排队点击……我只是在mac上安装了Edge:),它的工作原理与Chrome一样。我想问你是否专门在任何网站或选项卡上进行测试?@Loreno你可以尝试在edge上打开一个新的默认选项卡,看看它是否在那里工作。很好,所以与你在VSC中运行的网站有关的可能是:)我投票结束这个问题,因为它是由VS代码的扩展引起的问题。对,但问题是——为什么它在2015年的工作方式不同?:)对,我理解。我想知道的主要问题是,为什么它在2015年的工作方式有所不同(正如我们在YT视频中看到的),这取决于浏览器的具体实现,其中可能存在一些未定义的行为。我不确定。现在看看代码,你所描述的行为正是我从演示代码中所期望的。我也在Chromium下检查了代码-行为与视频中完全一样。我希望Edge和Chromium的行为基本相同,因为它们共享很多代码库,但这是它们之间的区别之一。Edge在运行期间根本不会注册单击。对,在Chromium下,它也会这样工作。我编辑了我的问题。在Edge下,它的工作原理不同。我刚刚在mac上安装了Edge:),它的工作原理和Chrome一样。我想问的是,您是否专门在任何站点或选项卡上进行测试?