异步计时器事件在 Firefox 4 中同步运行(“有问题”)?
这是在 Firefox 4 (4.0.1) 中; Firefox 3 (Firefox 3.6.17)、IE 9 (9.0.8112.16421) 和 Chrome 11 (11.0.696.68) 中的警报顺序“按预期”。
预期的警报顺序为“Now”、“Wait-End(x)”、“End(x)”,其中 x
是相同的数字。
但是,观察到的顺序是“Now”、“End(0)”、“Wait-End(x)”。为什么setTimeout
在while
之后不异步运行?正如计数器所示,这似乎可能非常有问题。 这是以下测试用例的 jsfiddle:
function doLater(callback) {
// if the timeout is larger than about 800ms it "works as expected"
setTimeout(callback, 1)
alert("Now")
}
var waiting = 0;
doLater(function () { alert("End(" + waiting + ")") })
var end = (+new Date) + 2000
while ((+new Date) < end) { waiting++ }
alert("Wait-End(" + waiting + ")")
如果计时器超时时间超过大约 800 毫秒,就会发生预期的行为。(100 毫秒和 500 毫秒的超时仍然表现出意外的顺序)。
这看起来真的像一个错误。
更新:这部分是海森堡的。以下内容按预期工作。 Firefox 4.0.1 中的 alert
似乎将处理待处理事件(何时关闭?)。 jsfiddle 和代码:
function doLater(callback) {
setTimeout(callback, 1)
console.log("Now")
}
var waiting = 0;
doLater(function () { console.log("End(" + waiting + ")") })
var end = (+new Date) + 2000
while ((+new Date) < end) { waiting++ }
console.log("Wait-End(" + waiting + ")")
有了这些新信息,Firefox 4 的警报行为仍然可以在适用的 Javascript / 中运行吗?事件模型规范?特别是,调用警报
的代码仍然是“活动的”,但效果是它暂时被事件处理抢占。
This is in Firefox 4 (4.0.1); The order of alerts is "as expected" in Firefox 3 (Firefox 3.6.17), IE 9 (9.0.8112.16421), and Chrome 11 (11.0.696.68).
The expected order of alerts is "Now", "Wait-End(x)", "End(x)"
, where x
is some number that is the same.
However, the observed order is "Now", "End(0)", "Wait-End(x)"
. Why does setTimeout
not run asynchronously after the while
? This seems like it could be very problematic, as shown with the counter. Here is the jsfiddle for the following test case:
function doLater(callback) {
// if the timeout is larger than about 800ms it "works as expected"
setTimeout(callback, 1)
alert("Now")
}
var waiting = 0;
doLater(function () { alert("End(" + waiting + ")") })
var end = (+new Date) + 2000
while ((+new Date) < end) { waiting++ }
alert("Wait-End(" + waiting + ")")
If the timer timeout is above ~800ms then the expected behavior occurs. (Timeouts of 100ms and 500ms still exhibit the unexpected order).
It really seems like a bug.
Update: This partially a Heisenberg. The following works as expected. It appears that alert
in Firefox 4.0.1 will process pending events (when closed?). The jsfiddle and code:
function doLater(callback) {
setTimeout(callback, 1)
console.log("Now")
}
var waiting = 0;
doLater(function () { console.log("End(" + waiting + ")") })
var end = (+new Date) + 2000
while ((+new Date) < end) { waiting++ }
console.log("Wait-End(" + waiting + ")")
With this new information, does Firefox 4's alert behavior still operate within applicable Javascript / event-model specifications? In particular, the code which invoked the alert
is still "active" but the effect is that it is being momentarily preempted with event processing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的脚本可以在我的 Firefox 3.6.17 中运行。
我做了一些搜索...看起来 Firefox 3 在处理
警报
时实际上停止了 JavaScript 线程。然而,其他同步操作(例如 XMLHttpRequest)使用了称为“事件循环”的东西,这显然不会阻止其他计时器的执行。我的猜测是,Firefox 4 现在对
alert
所做的事情与 Firefox 3 对XMLHttpRequest
所做的事情一样;它使用事件循环,因此计时器在警报“后面”运行。这似乎可以解释为什么它对我有用(在 FF3 中)但对你不起作用(在 FF4 中)。FF3 信息来源。
Your script works in my Firefox 3.6.17.
I did some searching... It would seem that Firefox 3 actually halted the JavaScript thread(s) when processing an
alert
. However, other synchronous operations (likeXMLHttpRequest
) instead used something called an "event loop", which apparently doesn't stop other timers from executing.My guess is that Firefox 4 is now doing for
alert
what Firefox 3 did forXMLHttpRequest
; it's using an event loop, and because of this, timers run "behind"alert
s. This would seem to explain why it works for me (in FF3) but not for you (in FF4).Source for the FF3 information.
我想说,您看到“预期”行为的唯一原因是,您在浏览器的计时器有机会触发回调之前,在 while 循环中引入了一个块。在您的
doLater
中,您已指示 JavaScript 引擎尽快执行callback
函数。但是,您随后立即引入一条指令,该指令将占用大多数 JavaScript 引擎,因此回调必须等待。因此,FireFox 4 的 JavaScript 引擎在这种情况下必须比其他引擎快一些。I'd say the only reason you are seeing your "expected" behavior is because you are introducing a block with your while loop before the browser's timer has had a chance to fire your callback. In your
doLater
you have instructed the JavaScript engine to execute thecallback
function as soon as possible. However, you then immediately introduce an instruction that will tie up most JavaScript engines so that thecallback
has to wait. So FireFox 4's JavaScript engine must be a bit quicker in this instance than the others.