在Firefox 4中同步运行异步计时器事件(“buggy”)?

时间:2011-05-21 20:57:42

标签: javascript events firefox

这是在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在<{em> while之后不能异步运行?这似乎可能非常有问题,如计数器所示。 Here is the 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 + ")")

如果定时器超时超过~800ms,则会出现预期的行为。 (100ms和500ms的超时仍显示意外顺序)。

这看起来真是个错误。


更新:此部分海森堡。以下按预期工作。似乎Firefox 4.0.1 中的alert将处理待处理事件(关闭时?)。 The 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 /事件模型规范中运行?特别是,调用alert的代码仍处于“活动状态”但是效果是它暂时被事件处理抢占。

2 个答案:

答案 0 :(得分:1)

我说你看到“预期”行为的唯一原因是因为你在浏览器的计时器有机会触发回调之前引入了一个带有while循环的块。在doLater中,您已指示JavaScript引擎尽快执行callback功能。但是,然后,您会立即引入一条指令,该指令将占用大多数JavaScript引擎,以便callback必须等待。因此,在这种情况下,FireFox 4的JavaScript引擎必须比其他引擎快一点。

答案 1 :(得分:1)

您的脚本适用于我的Firefox 3.6.17。

我做了一些搜索......似乎Firefox 3在处理alert时实际上停止了JavaScript线程。但是,其他同步操作(如XMLHttpRequest)改为使用称为“事件循环”的东西,这显然不会阻止其他计时器执行。

我的猜测是Firefox 4现在正在为{3}用于alert的Firefox XMLHttpRequest它使用了一个事件循环,因此,定时器运行在“alert后面”。这似乎可以解释为什么它适用于我(在FF3中)但不适合你(在FF4中)。

Source for the FF3 information.