【问题标题】:Why does event handler wait until triggering code completes execution?为什么事件处理程序要等到触发代码完成执行?
【发布时间】:2019-05-22 21:32:16
【问题描述】:

以下 sn-p 说明了我的问题。我有一些代码调用jQuery.trigger 处理customeventstart 事件,然后进行一些密集处理,然后再次调用jQuery.trigger 处理customeventstop 事件。

我希望customeventstart 的事件处理程序立即执行。但是,在控制台显示 customeventstart 处理程序的结果之前存在明显的延迟。似乎直到触发代码完成执行后才会调用事件处理程序。

注意:您可以根据机器的处理能力调整代码 sn-p 中循环的迭代次数,以延长/缩短延迟。

btn = $('#btn');

btn.on('click', function() {
  btn.trigger('customeventstart');
  
  // intensive/time-consuming processing
  for (var i = 0; i < 100000000; ++i) {
    'string' + 'concatenation'; 
  }
  console.log('intensive processing done');
  
  btn.trigger('customeventstop');
});

btn.on('customeventstart', function() {
  console.log('starting');
});

btn.on('customeventstop', function() {
  console.log('stopping');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">This may take a while</button>

我计划使用异步 Web Workers 解决方案,但我想更好地了解发生了什么。

为什么jQuery.triggered 事件的处理程序要等待或似乎要等到触发代码完成?

【问题讨论】:

  • 所有 jQuery 事件,据我所知(可能有例外,因为我不是上帝),同步执行。这可能是给您带来明显“延迟”的原因。
  • “但是,在控制台显示 customeventstart 处理程序的结果之前存在明显的延迟。” 在什么浏览器上?对于 Chrome 上的我来说,延迟在 0 到 8 毫秒的范围内。这是我用来记录那些时间的片段:pastie.org/9975343 时间似乎也与我所看到的相符,但人类最多只能准确到大约 50-100 毫秒,而我这个年龄 [48] 的人类可能接近尾声那种规模。 :-)
  • @T.J.Crowder 感谢您的 sn-p。对我来说,它在 Firefox 中接近 800 毫秒。但这应该非常依赖于系统,对吧?我现在正在运行其他选项卡/流媒体视频/软件。我正在开发一个需要大量扩展的系统(不确定多少),因此我担心保持 UI 响应。

标签: javascript jquery events jquery-events


【解决方案1】:

我认为这与 Firefox(和 Firebug)中的 console.log 实现有关,而不是事件的实际时间。

我尝试对您的 sn-p 进行以下修改,基本上只是添加了 Date.now 和一些控制台日志语句:

btn = $('#btn');

btn.on('click', function() {
  console.log(Date.now() + ': triggering customeventstart');
  btn.trigger('customeventstart');
  
  // intensive/time-consuming processing
  console.log(Date.now() + ': starting intensive processing');
  for (var i = 0; i < 100000000; ++i) {
    'string' + 'concatenation'; 
  }
  console.log(Date.now() + ': intensive processing done');
  
  console.log(Date.now() + ': triggering customeventstop');
  btn.trigger('customeventstop');
});

btn.on('customeventstart', function() {
  console.log(Date.now() + ': starting');
});

btn.on('customeventstop', function() {
  console.log(Date.now() + ': stopping');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">This may take a while</button>

对我来说:

  • 在 Chrome 和 IE11 上,单击该按钮会导致前三个日志语句(通过“开始密集处理”)几乎即时记录,然后是延迟,然后是其余行。而顺序和时间是由线路上的时间戳来证明的。

  • 在 Firefox 上,单击按钮会导致延迟,然后所有行一起出现 - 但如果您查看时间戳,很明显延迟实际上发生在“开始密集处理”和“密集处理”之间完成”日志语句,与 Chrome 和 IE11 一样(我必须在循环最大值中添加 0 才能在 Firefox 中看到这一点——哇,这些天这些东西速度很快):

“1424713006530:触发 customeventstart” “1424713006530:开始” “1424713006531:开始强化处理” “1424713007263:密集处理完成” “1424713007263:触发customeventstop” “1424713007264:停止”

所以并不是事件在延迟后被触发,而是如果主 UI 线程很忙,Firefox 的 console.log 实现似乎被阻止了。

这与浏览器可能不会在主 UI 线程繁忙时更新页面显示的通常情况非常相似。例如,在下面的 sn-p 中,我们在进行密集处理时将按钮的背景变为红色(根本不使用任何自定义事件),然后在完成后将其恢复;但在大多数浏览器上,您根本看不到按钮的背景变化,即使在处理过程中有足够的时间:

btn = $('#btn');

btn.on('click', function() {
  console.log(Date.now() + ': turning button background red');
  btn.css('background-color', 'red');
  
  // intensive/time-consuming processing
  console.log(Date.now() + ': starting intensive processing');
  for (var i = 0; i < 100000000; ++i) {
    'string' + 'concatenation'; 
  }
  console.log(Date.now() + ': intensive processing done');
  
  console.log(Date.now() + ': restoring button background');
  btn.css('background-color', '');
});
(Look in the console.)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">This may take a while</button>

【讨论】:

  • 很有趣,但我认为还有其他事情发生。当我唯一要做的事情就是记录时,我确实得到了你在 Chrome 中谈论的结果。但是,如果我真的尝试做除了console.logs 之外的事情,我会在 Chrome 和 FF 中得到延迟。看看这个 jsfiddle:jsfiddle.net/24ttk41c/2.
  • @blcook223:这完全是另一回事。浏览器在主 UI 线程集中处理时更新显示的情况并不少见。没有事件你会得到同样的效果:jsfiddle.net/24ttk41c/3
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-19
  • 2016-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多