JavaScript 事件处理的竞争条件?

Posted

技术标签:

【中文标题】JavaScript 事件处理的竞争条件?【英文标题】:Race conditions with JavaScript event handling? 【发布时间】:2012-01-26 12:34:07 【问题描述】:

我们了解 javascript 是单线程的,但我们想确认我们对 JavaScript 中的异步事件处理的理解。更重要的是,我们想确认我们没有面临潜在的竞争条件。

从概念上讲,我们的移动应用程序是这样工作的:

    我们在加载移动页面时调用函数foo

    foo 的末尾,如果计数器大于0,我们使用setTimeout 再次调用foo(延迟一秒)。如果计数器命中0,我们会加载一个新页面。超时保存在一个变量中。

    如果点击按钮,我们调用函数do_tap 并清除第二步中保存的超时变量(并执行其他操作)。

do_tapfoo 都更新了同一个页面元素,我们想确认它们不会互相踩踏。

问题:

    假设在foo 的执行过程中发生了点击。浏览器队列do_tap 会在foo 完成后开始执行吗?换句话说,我们是否保证一旦foo 启动,我们就永远看不到foodo_tap 交错执行?

    如果先点击怎么办? do_tap 保证在 foo 开始之前完成,对吧?

【问题讨论】:

由于执行是单线程的,foo 根本不可能在返回Do_tap 之前开始执行(反之亦然)。阅读这篇文章,您将了解浏览器中的执行队列是如何工作的:ejohn.org/blog/how-javascript-timers-work 【参考方案1】:

除了网络工作者和协作框架或窗口(此处未使用)外,Javascript 在给定窗口中是单线程的,因此在该窗口中永远不会有两个执行线程同时运行。因此,您不必担心在使用线程时可能是典型的竞争条件。

在幕后,Javascript 有一个事件队列。您当前的执行线程将运行到完成,然后当它完成时,javascript 解释器将检查事件队列以查看是否还有更多事情要做。如果是这样,它会触发该事件并启动另一个执行线程。几乎所有事情都经过该事件队列(计时器、按键事件、调整大小事件、鼠标事件等...)。

您可以在my other answers 之一中阅读有关此主题的更多信息并查看大量相关参考资料。

【讨论】:

这几乎是真的,除了帧有不同的执行上下文,如果它们都访问相同的数据,比如top.myVariable,你可能会有竞争条件。请参阅dev.opera.com/articles/view/… 并在该页面中搜索种族 我还想提一下 Chrome 扩展,您可以在其中拥有多个单独的执行上下文。我没有发现竞争条件经常发生,很大程度上取决于您正在构建的内容,但确实会发生。【参考方案2】:

事件执行单线程进行,直到事件被处理。在此之前,不会启动其他事件循环。

换句话说,当某个事件的处理程序正在运行时,任何其他事件的其他处理程序都不会中断它。

因此,问题 1 和问题 2 的答案都是“是”。 (当然,这是排除浏览器错误,但如果你考虑到这一点,你就不会走得太远。这不像是有任何同步原语可以依靠。我这么说只是因为有一段时间在此期间,Safari 可能会在运行另一个“DOMready”事件处理程序的过程中触发“DOMready”事件。然而,这显然是一个错误。)

【讨论】:

谢谢,我们只是想确认一下! do_tap() 和 foo() 都更新同一个页面元素,我们希望确保它们不会互相踩踏。再次感谢您的肯定。【参考方案3】:

只要 Do_tap() 做的第一件事是 clearTimeout,在 Do_tap() 执行期间 foo 就没有机会运行。但是,如果在 foo() 中启动了这样一个数据库请求的异步进程,那么当 foo() 完成其请求时,可能会在 Do_tap() 中等待访问数据库,并且如果 foo() 有一个回调函数可以理论上在 Do_tap() 执行完成后调用。

【讨论】:

【参考方案4】:

我没有听到其他人这么说,但我认为#2 的答案是,不同的浏览器实现可以并且确实以微妙的方式不同,即首先处理哪些排队事件。不,没有交错的可能性,但是语言规范不能保证首先处理 setTimeout(func, 0) 还是鼠标事件,实际上可能很重要。而 setTimeout(func, 100) 保证在当前处理的事件期间接收到的挂起事件之后处理。

只是说。

【讨论】:

以上是关于JavaScript 事件处理的竞争条件?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript事件简述

JavaScript ---[事件,Event对象]

Flutter BLoC 事件竞争条件

HTML 事件属性(如:onsubmit)

浅谈JavaScript的事件(事件处理程序)

前端—— JavaScript基础操作:if语句for循环while循环for...infor...of异常处理函数事件JS选择器JS操作页面样式