Javascript Firefox4中同步运行的异步计时器事件(“buggy”)?

Javascript Firefox4中同步运行的异步计时器事件(“buggy”)?,javascript,events,firefox,Javascript,Events,Firefox,这是Firefox4(4.0.1);Firefox3(Firefox3.6.17)、IE 9(9.0.8112.16421)和Chrome11(11.0.696.68)中的警报顺序与预期一致 警报的预期顺序为“现在”、“等待结束(x)”、“结束(x)”,其中x是相同的数字 但是,观察到的顺序是“现在”、“结束(0)”、“等待结束(x)”。为什么setTimeout在while之后不异步运行?这似乎是非常有问题的,如计数器所示。对于以下测试用例: function doLater(callback

这是Firefox4(4.0.1);Firefox3(Firefox3.6.17)、IE 9(9.0.8112.16421)和Chrome11(11.0.696.68)中的警报顺序与预期一致

警报的预期顺序为“现在”、“等待结束(x)”、“结束(x)”,其中
x
是相同的数字

但是,观察到的顺序是“现在”、“结束(0)”、“等待结束(x)”。为什么
setTimeout
while
之后不异步运行?这似乎是非常有问题的,如计数器所示。对于以下测试用例:

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 + ")")

有了这些新信息,Firefox 4的警报行为是否仍在适用的Javascript/事件模型规范范围内运行?特别是,调用
警报的代码仍处于“活动状态”但其效果是,它会被事件处理暂时抢占。

我想说,您看到“预期”行为的唯一原因是,在浏览器计时器触发回调之前,您在while循环中引入了一个块。在
doLater
中,您已指示JavaScript引擎尽快执行
回调
函数。但是,随后立即引入一条指令,该指令将占用大多数JavaScript引擎,因此
回调必须等待。因此,在本例中,Firefox4的JavaScript引擎必须比其他引擎快一点。

您的脚本在我的FireFox 3.6.17中工作

我做了一些搜索。。。在处理
警报时,Firefox3似乎实际上停止了JavaScript线程。然而,其他同步操作(如
XMLHttpRequest
)却使用了一种称为“事件循环”的方法,这显然不会阻止其他计时器的执行

我猜Firefox4现在正在为
alert
做什么,就像Firefox3为
XMLHttpRequest
做的一样;它使用一个事件循环,正因为如此,计时器在警报后运行。这似乎可以解释为什么它适用于我(在FF3中)而不适用于你(在FF4中)


我检查了小提琴;在Firefox 3.6.17中,警报以正确的顺序显示。奇怪的是,执行顺序在不同版本之间发生了变化。。。但据我所知,从一开始就没有任何保证您的函数能够以“正确”的顺序运行(因为它们都是异步的)。@DavidJCobb感谢Firefox 3.6上的报告。我觉得订单是有保证的;也就是说,异步事件不能抢占当前正在执行的Javascript。。。我做了一些搜索,发现了一篇文章,其中指出Firefox3在调用
警报
时停止了JavaScript线程的执行,但当其他同步操作(如
XMLHttpRequest
)运行时(意味着其他计时器未被阻止),FF3使用了“事件循环”。通过使用事件循环,FF4可能正在为
alert
执行FF3为
XMLHttpRequest
执行的操作。FF3信息来源:@DavidJCobb-Wow。很好的发现。我根本没想到FF会这么做(这看起来像是一个愚蠢的实现缺陷…呃…细节),但我同意这是同一个场景。考虑发表一个答案,我不同意这个观点。如果它是正确的,那么这意味着Javascript异步事件可以抢占其他Javascript代码,这与基于事件的调度模型背道而驰。此外,500毫秒的超时(对于计算机来说这是一个非常长的时间)仍然会表现出“意外”的行为。我仍然不同意这个答案,但指出了时间,我用测试用例替换了
alert
,并找到了一个海森堡。所以a+1,谢谢:-)我用更多的细节更新了我的问题。至少它有帮助。我仍然不确定执行命令是否能保证是你在这里期望的命令。请原谅让你永远等待;-)虽然这个源不是确切的情况,但它是相关的——一个意外的事件循环被存根到一个“同步”上下文中。我仍然相信这是一个“错误”,但它是什么。
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 + ")")