Javascript 为什么超时会在“暂停”之前触发;点击";Firefox上的事件循环是否已完成?
步骤:Javascript 为什么超时会在“暂停”之前触发;点击";Firefox上的事件循环是否已完成?,javascript,firefox,confirm,Javascript,Firefox,Confirm,步骤: 在Firefox中运行代码 等待5秒钟(重要!) 按OK或Cancel expect flag==0,但它是10 var标志; 函数myFunction(){ 标志=0 控制台信息(“初始”,标志); setTimeout(函数(){ flag=10; }, 200); 确认(“确认”); 警报(“应为0:+标志); } document.getElementById('button').onclick=myFunction; 点击我什么?您将flag设置为10。为什么您希望它是0?
var标志;
函数myFunction(){
标志=0
控制台信息(“初始”,标志);
setTimeout(函数(){
flag=10;
}, 200);
确认(“确认”);
警报(“应为0:+标志);
}
document.getElementById('button').onclick=myFunction;
点击我代码>什么?您将flag设置为10。为什么您希望它是0?因为与许多浏览器不同,Firefox可能允许JavaScript线程在显示警报
、提示
和确认
模块时运行其他代码,从而挂起当前代码。(有关该句中“可能”的更多信息,请参见答案末尾。)调用了警报
等的任务被挂起,因此该任务中的代码不会继续,但允许运行其他任务
这意味着
- 计时器可以得到它们的回调
- Ajax完成处理程序可以运行
- 等等
从来没有JavaScript在两个地方同时运行,但是Firefox允许线程运行其他任务,而任务被这些模式挂起
这是Firefox的一个怪癖。我第一次了解它就在这里的堆栈溢出
为什么我说“可以”让JavaScript线程运行:它过去相当可靠(Firefox的旧版本)。我在Firefox 29或38上复制它没有问题。Firefox42似乎使其可能性大大降低,但它仍然会发生
我预计(尽管我可能错了)Mozilla会改变这一点,使之与其他浏览器保持一致,因为有人可能会说它违反了JavaScript的任务从运行到完成的语义,而这些语义刚刚得到了最新规范的强化和澄清。我在Firefox和Chrome中都尝试过。在Firefox中,我得到了10
。在Chrome中,我得到了0
的结果。当涉及到confirm
功能时,Firefox和Chrome可能有不同的并发模型。Firefox可能在一个单独的线程中运行模式对话框,允许setTimeout
在自己的线程中继续运行(并在200毫秒后增加标志的值)。Chrome可能在与setTimeout
相同的线程中运行模式对话框,从而阻止setTimeout
的运行(并且不允许标志的值增加)。我等待了30秒,但仍然显示0。现在不要告诉我,应该只有5秒钟我想问题是,为什么在“点击”事件循环完成之前触发超时。当“点击”事件循环仍然处于活动状态时,计时器事件是如何发生的?“为什么您希望它为0?”因为在Chrome、IE和Safari上,它是0
confirm
是内置的stop-the-world模式之一。除了Firefox,还有新的浏览器版本吗?我不能复制。我也可以在Windows上的Firefox 42.0上复制。@vitalh:真的吗?我不能(只是仔细检查一下)。你刚刚更新了吗?@vitalh:我刚刚尝试了一个带有Firefox 41的Windows 8.1系统,结果是0,而不是10。(我的Firefox42测试是在旧版本的Windows上进行的。)@t-j-crowder。否。我在发布后立即更新。