【问题标题】:Understanding how alert() impacts browser event loop了解 alert() 如何影响浏览器事件循环
【发布时间】:2011-06-07 17:11:17
【问题描述】:

我正在考虑将alert() 添加到我们的 Javascript 实用程序断言函数中。

我们是一个 ajax-heavy 应用程序,我们的框架 (Ext) 通过使用 setInterval 轮询 ajax 响应而不是等待 readystate==4 来实现 ajax,导致我们所有的 ajax 回调在一个setInterval 堆栈上下文——以及一个异常/断言吹出它通常会静默失败。

低级 alert() 如何影响浏览器事件循环?根据定义,消息框必须允许 win32 事件循环进行泵送(以响应 mbox 按钮)。这是否意味着其他浏览器事件,例如由我们的框架生成的未来setIntervals、调整大小事件等,将会触发?这会给我带来麻烦吗?

IIRC:你可以使用 Firefox2 和 Firefox3.5 来看看我说的区别。

alert('1');
setTimeout(function(){alert('2');}, 10);
alert('3');

Firefox3.5 显示 1-3-2。 Firefox2[1] 显示 1-2&3(2 和 3 同时堆叠在一起)。我们也可以使用从 ActiveX 启动的 win32 mbox 在 IE8 中复制 1-2&3,而不是发出警报,这在当天对我们造成了严重破坏,我想确保我们不会再走这条路。

谁能指出具体的低级资源来解释这种行为,这里的预期行为是什么,以及低级到底发生了什么,包括为什么行为在 Firefox 版本之间发生变化?

[1] 你可以在 Spoon.net 上复制这个,我现在无法工作。我刚刚在带有 Firefox 2.0.0.20 的 VM 中复制了它。

【问题讨论】:

  • 很好的问题。以我的经验,alert 的实现在不同的浏览器中差别很大。一般来说,我会避免alert 这些事情很重要,并使用自定义(即 jQuery UI 样式)对话框。
  • @Oliver -- 是的,我们实际上选择使用基于 DOM 的弹出窗口,但我仍然想了解警报的内部结构。
  • “根据定义,消息框必须允许 win32 事件循环泵送”——某些操作系统——例如 Mac OS X——使用嵌套事件循环。警报可能会运行自己的modal event loop,它会阻塞主事件循环。一些网络浏览器可能会为对话框做类似的事情。

标签: javascript winapi dom-events settimeout


【解决方案1】:

首先,javascript 中的计时器不是很精确。小于 30 毫秒的间隔可能被认为是相同的,并且实现方式各不相同。不要依赖任何隐式排序。

alert() 将始终停止事件循环。如果在警报期间触发事件或计时器,它们将在事件循环恢复(警报框关闭)后排队并调用。

举个例子:

var hello = document.getElementById('hello')

setTimeout(function(){
  hello.style.backgroundColor = 'lime'
}, 5000)

alert('Stop!')

setTimeout(function(){
  hello.innerHTML = 'collaborate'
}, 20)

setTimeout(function(){
  hello.innerHTML = 'listen'
}, 1000)

有两种可能的结果:

  1. 您在 5 秒内关闭警报框。随后的两个计时器将按指定的时间间隔设置和触发。您可以看到事件循环已停止,因为无论您等待多长时间关闭警报,“侦听”始终需要 1 秒才能执行。

  2. 关闭警报的时间超过 5 秒。第一个间隔 (bgColor) 已经过去,因此它立即执行,然后设置并调用两个计时器。

http://jsbin.com/iheyi4/edit

至于间隔,当事件循环停止时,它也“停止时间”,所以在这种情况下:

i = 0

setInterval(function(){
  document.getElementById('n').innerHTML = ++i
}, 1000)

setTimeout(function(){
  alert('stop')
}, 5500)

无论您关闭警报需要多长时间,下一个数字将始终为 6 - setInterval 不会触发多次。

http://jsbin.com/urizo6/edit

【讨论】:

  • 优点。 An alert() will always halt the event loop 好吧,浏览器进程的 win32 消息泵至少正在处理 wm_paint,因为如果我们移动 mbox,它会重绘。 setInterval 在 FF3+ 中等待是因为 wm_timer 没有处理,还是因为与 javascript vm 进行了一些花哨的交互?
  • @Dustin:javascript 事件循环明显不同于 win32 事件队列(win32 中没有隐式循环)。我很确定 WM_TIMER 一直都在正常处理,只有实现 javscript 超时的方式使它看起来不同。
【解决方案2】:

我无法复制 1-2&3 的情况,但 here 是一个可以帮助您调试不同浏览器中发生的事情的小提琴。

【讨论】:

  • @Dustin Getz 没问题,希望对您有所帮助!
猜你喜欢
  • 2011-07-22
  • 2022-01-24
  • 1970-01-01
  • 2021-11-03
相关资源
最近更新 更多