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?

步骤:

  • 在Firefox中运行代码
  • 等待5秒钟(重要!)
  • 按OK或Cancel
  • expect flag==0,但它是10
  • 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。否。我在发布后立即更新。