2011-12-23 106 views
4

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

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

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

  2. 截至foo最后,我们使用setTimeout再次调用foo(以一秒的延迟)如果计数器大于0更大。如果计数器遇到0,我们将加载一个新页面。超时保存在一个变量中。

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

do_tapfoo更新都在同一个页面元素,我们想确认,他们不会互相步骤。

问题:

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

  2. 如果水龙头先出现怎么办? do_tap保证在foo开始前完成,对吧?

+0

由于执行是单线程的,因此'foo'在'Do_tap'返回之前开始执行是根本不可能的(反之亦然)。阅读本文,您将了解浏览器中的执行队列是如何工作的:http://ejohn.org/blog/how-javascript-timers-work/ – 2011-12-23 00:35:56

回答

6

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

在封面下,Javascript有一个事件队列。您当前的执行线程将运行至完成,然后当完成时,JavaScript解释器将检查事件队列以查看是否有更多事情要做。如果是这样,它会触发该事件并启动另一个执行线程。几乎所有的事情都经历了事件队列(定时器,重要事件,调整大小事件,鼠标事件等)。

您可以阅读更多关于它的信息,并在my other answers的其中一个相关参考资料中查看该主题。

+1

这几乎是正确的,除了框架具有独立的执行上下文,并且如果它们都访问相同的数据,如'top.myVariable',则可能有竞争条件。查看http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/并在该页面搜索竞赛 – 2013-09-16 22:32:41

+0

@JuanMendes - 好点。我会更新我的答案。 – jfriend00 2013-09-17 06:20:23

4

事件执行进行到单线程,直到事件已被处理。直到那个时候,没有其他事件循环将被启动。

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

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

+0

谢谢,我们只是想确认! do_tap()和foo()都更新相同的页面元素,我们希望确保它们不能互相踩在一起。再次感谢您的肯定。 – Crashalot 2011-12-23 00:27:26

0

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

0

我没有听到任何其他人这样说,但我认为#2的答案是不同的浏览器实现能够并且确实以微妙的方式区分哪些排队事件是首先处理的。不,不存在交错的可能性,但是setTimeout(func,0)或鼠标事件是否先被处理不受语言规范的保证,并且在实践中可能很重要。而setTimeout(func,100)保证在当前处理的事件期间接收到的待处理事件之后处理。

只是说。