Asynchronous timer event running synchronously ("buggy") in Firefox 4?
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 appear开发者_StackOverflow社区s 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.
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 (like XMLHttpRequest
) 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 for XMLHttpRequest
; 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.
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 the callback
function as soon as possible. However, you then immediately introduce an instruction that will tie up most JavaScript engines so that the callback
has to wait. So FireFox 4's JavaScript engine must be a bit quicker in this instance than the others.
精彩评论