竞争条件与JavaScript事件处理
Race conditions with JavaScript event handling?
我们知道JavaScript是单线程的,但是我们想确认一下我们对JavaScript中异步事件处理的理解。更重要的是,我们要确认我们没有暴露在潜在的竞争条件下。
从概念上讲,我们的移动应用程序是这样工作的:我们在加载移动页面时调用
foo
函数在
foo
结束时,如果计数器大于0
,我们使用setTimeout
再次调用foo
(延迟1秒)。如果计数器到达0
,我们加载一个新页面。超时保存在一个变量中如果按钮被点击,我们调用
do_tap
函数并清除在步骤2中保存的超时变量(并做其他事情)。
do_tap
和foo
都更新了相同的页面元素,我们想确认它们不会相互踩到。
问题:
假设在
foo
执行过程中发生轻拍。浏览器队列do_tap
会在foo
完成后开始执行吗?换句话说,我们能保证一旦foo
启动,我们永远不会看到foo
和do_tap
的执行交错吗?如果tap先发生怎么办?
do_tap
保证在foo
开始之前完成,对吗?
除了web worker和协作框架或窗口(这里没有使用),Javascript在给定窗口内是单线程的,因此在该窗口中永远不会同时运行两个执行线程。因此,您永远不必担心竞争条件,这可能是使用线程时常见的问题。
在幕后,Javascript有一个事件队列。当前执行的线程将运行到完成,然后当它完成时,javascript解释器将检查事件队列,看看是否还有更多的事情要做。如果是,则触发该事件并启动另一个执行线程。几乎所有事情都要经过这个事件队列(计时器、按键事件、调整大小事件、鼠标事件等)。你可以在我关于这个主题的另一个答案中阅读更多相关的参考资料。
事件继续单线程执行,直到事件被处理。在此之前,不会启动其他事件循环。
换句话说,当一个处理程序正在为某个事件运行时,其他任何事件的处理程序都不会中断它。
因此问题1和问题2的答案都是"是"。(当然,这是排除浏览器漏洞,但如果你考虑到这一点,你就不能走得太远。这并不是说有什么同步原语可以依赖。我这么说只是因为在运行另一个"DOMready"事件处理程序的过程中,有一段时间Safari可能会触发一个"DOMready"事件。然而,这显然是一个bug。)
只要Do_tap()所做的第一件事是clearartimeout,那么在Do_tap()执行期间就没有机会运行foo。然而,如果在foo()中启动了一个异步进程,这样一个数据库请求,那么在foo()完成它的请求时,可能会有一个潜在的等待来访问Do_tap()中的数据库,如果foo()有一个回调函数,理论上可以在Do_tap()完成执行后调用。
我没有听到其他人这么说,但我认为第2点的答案是,不同的浏览器实现在首先处理哪个队列事件方面可能而且确实存在细微的差异。不,没有交错的可能性,但是语言规范不能保证首先处理setTimeout(func, 0)或鼠标事件,在实践中可能很重要。而setTimeout(func, 100) 保证在当前处理事件期间接收到的挂起事件之后处理。
只是说。
- 提示使用服务器端事件处理程序激活JavaScript
- 在同一个javascript事件处理程序中调用不同的函数
- 如何使用Node.js在JavaScript模块文件之间使用事件处理程序
- 带有参数的Javascript事件处理程序
- 如何从另一个处理程序内部取消JavaScript事件处理程序函数的执行
- 如何在 JavaScript 代码中调试点击事件处理
- 多个类上的Javascript onclick事件处理程序
- 当用户允许使用mic Javascript时,事件处理程序是什么
- 撤消javascript中的所有鼠标事件处理程序
- 如何在事件处理程序中获取 javascript 事件对象
- JavaScript 事件处理具有延迟的滚动事件
- 如何查找触发或处理事件的 Javascript
- 测试 JavaScript Zombie 事件处理程序或 DOM 元素
- 如何将 Promise 添加到 javascript 中的事件处理程序
- 有没有办法用Javascript找到元素的事件处理程序
- 用于逐步增强的“select”元素的JavaScript中的事件处理程序
- 如何删除DOM事件处理程序的重复JavaScript代码
- 事件处理-JavaScript'return false'仅与HTML联机工作
- 如何使用元素检查器在网站上运行我自己的事件处理Javascript代码
- 事件处理- Javascript addEventListener不读取resize