DOM事件总是运行单线程吗?

时间:2013-09-16 15:51:01

标签: javascript multithreading dom javascript-events event-handling

所以我answered a question最近和OP问我是否可以将以下关于DOM事件的内容添加到我的答案中:

  

也许您还可以在答案中添加不仅首先执行它们,而且在第一个事件结束之前阻止后续事件。

嗯,可以我添加吗?我知道使用DOM事件会一次运行一个事件并等待上一个事件在下一个事件开始之前完成吗?

我至少知道浏览器JavaScript总是如此吗?

到目前为止,找到一个确凿的答案令人惊讶地难以实现,我预计会有“是”,但我找不到它。


澄清:我不是要求在处理程序中添加其他异步处理程序,或者调用setTimeout或worker等。我要问的是,事件处理程序执行的顺序是否得到保证,下一个程序是否只启动了前一个执行完成的程序?一个好的答案会引用一个可靠的来源(最好是一个规范)。没有关于穿线的事。

2 个答案:

答案 0 :(得分:5)

Yes and no,所有JS都在同一个线程上运行,除了没有访问DOM的Web worker。 http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/

以下是该页面的一些相关信息

  

在处理下一个事件之前,所有事件处理函数都是按顺序执行的,并且每个事件都会被完全处理(包括通过DOM冒泡并执行默认操作)。

但是,稍后在该页面上,他们提到

  

比赛条件

     

每个窗口(和框架)都有自己的事件队列。   在Opera中,每个窗口都有自己的JavaScript线程。这包括iframe中的窗口。结果是从不同帧启动的事件处理程序可能同时执行。如果这些同步脚本修改共享数据(如顶部窗口中的属性),我们就有可能出现竞争条件。

事件全部放入事件队列,所有事件处理都在同一个线程内发生。与所有异步回调一起,如XHR和setTimeout

还要注意嵌套事件,因为如果触发事件并且可以更改全局状态,则会执行许多方法。示例http://jsfiddle.net/rpxZ4/

$('#d1').click(function(){
    alert('before ');
    $('#d2').trigger('click');
    $('#d3').trigger('click'); 
    alert('after ');
});

$('#d2, #d3').click(function() {
    alert('clicked ' +this.id);
});

这是Opera关于处理时间的建议

  • 没有长时间运行的脚本。
  • 不要使用同步XMLHttpRequests。
  • 不要让从不同帧启动的脚本操纵相同的全局状态。
  • 不要使用警告框进行调试,因为它们可能会完全改变程序的逻辑。

答案 1 :(得分:1)

那么,这实际上取决于你在处理程序中做了什么,以及如何定义第一个处理程序结束时刻?

例如,如果您只在eventHandler1中执行同步操作,那么您确定在eventHandler1完成之前不会触发eventHandler2。原因是javascript是单线程的。

但是,想象这样的场景: 单击button1触发eventHandler1,它实际上发出ajax请求。在那种情况下,你实际上认为什么是'eventHandler1'的结尾?如果是ajax请求返回的那一刻,那么eventHandler2将在eventHandler1完成之前启动(并可能结束)执行。

简而言之:只要您执行仅同步操作>订单有保证。

从评论中添加:

例如,

http://www.w3.org/TR/DOM-Level-3-Events/#sync-async,它说:“此虚拟队列中的每个事件都必须延迟,直到上一个事件完成其传播行为或被取消。”


那么,现在我们回到'我们在谈论什么类型的事件'的问题?如前所述:如果是异步事件,那么确保订单无法保证。但最初的困境是关于点击事件,而且一个不是异步而是同步。对于同步事件,文档清楚地指出:同步事件(“同步事件”)必须被视为它们在先进先出模型中的虚拟队列中,按照时间序列的顺序排序,相对于其他事件,DOM中的更改以及用户交互。


是的,没有保证。现在添加单线程javascript进入播放,你不能让它们同时执行。但是,严格说到DOM - 不能保证以前会发生什么。


再多一条评论......您可能拥有完全相同的DOM但可以从Java多线程环境访问。那么呢?:)然后你必须实现你自己的线程安全的异步事件处理,因为你不再像单独的线程环境那样“保护”javascript。所以,结论,正如我所看到的那样,DOM规范确实需要实现同步事件。异步事件执行取决于堆栈/线程实现。在Javascript中,这意味着2个处理程序不能重叠,但在Java中,例如不一定是指。