JavaScript事件处理的竞争条件?

我们知道JavaScript是单线程的,但我们想要确认我们对JavaScript中异步事件处理的理解。 更重要的是,我们想确认我们没有暴露于潜在的竞争条件。

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

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

  2. foo结束时,如果计数器大于0 ,我们使用setTimeout再次调用foo (延迟一秒)。 如果计数器达到0 ,我们加载一个新页面。 超时保存在变量中。

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

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

问题:

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

  2. 如果首先出现水龙头怎么办? 保证do_tapfoo启动之前完成,对吗?

除了Web worker和合作框架或窗口(这里没有使用)之外,Javascript在给定窗口中是单线程的,因此在该窗口中永远不会有两个执行线程同时运行。 因此,在使用线程时,您不必担心可能是典型问题的竞争条件。

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

您可以阅读更多相关信息,并在我关于此主题的其他答案中查看大量相关参考资料。

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

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

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

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

我没有抓到其他任何人这样说,但我认为#2的答案是不同的浏览器实现可以并且确实区别于首先处理哪些排队事件。 不,没有交错的可能性,但是语言规范无法保证是否首先处理setTimeout(func,0)或鼠标事件,并且在实践中可能很重要。 而setTimeout(func,100)保证比当前处理的事件期间收到的待处理事件处理得晚。

只是说。