为什么超时会在"点击"之前触发在Firefox上完成事件循环?

时间:2015-11-16 17:27:09

标签: javascript firefox confirm

步骤:

  1. 在Firefox中运行代码
  2. 等待5秒钟(重要!)
  3. 按OK或取消
  4. 期望flag == 0,但它是10。
  5. 
    
    pprint
    
    var flag;
    
    function myFunction(){
        flag = 0 
        console.info("initial", flag);
        setTimeout(function(){
            flag = 10;
        }, 200);
      
        confirm("conf");
       
        alert("should be 0: "+flag);
    }
    
    document.getElementById('button').onclick=myFunction;
       
                              
    
    
    

3 个答案:

答案 0 :(得分:5)

因为与许多浏览器不同,Firefox 可能允许JavaScript线程在显示alertpromptconfirm模式时运行其他代码,暂停当前代码。 (有关"可能"在该句子中的更多信息,请参阅答案的结尾。)alert等被调用的任务被暂停,因此该任务中的代码不会被执行继续,但允许其他任务运行。

这意味着

  • 计时器可以获得回调

  • Ajax完成处理程序可以运行

从来没有JavaScript在两个地方同时运行 ,但Firefox确实让线程运行其他任务,而任务被这些模态暂停。

这是一个Firefox的怪癖。我首先在Stack Overflow上了解了它,thanks to bobince

为什么我说"可能"允许JavaScript线程运行:它曾经相当可靠(Firefox的旧版本)。我在Firefox 29或38上复制它没有遇到任何麻烦.Firefox 42似乎不太可能,但 仍然会发生。

我希望(虽然我可能错了)Mozilla会将其改为与其他浏览器一致,因为人们可能会认为它违反了JavaScript的任务运行完成语义,而那些语义只是最新的规范得到了加强和澄清。

答案 1 :(得分:1)

我在Firefox和Chrome中都尝试了this。在Firefox中,我得到了10的结果。在Chrome中,我得到了0的结果。在confirm函数中,Firefox和Chrome可能有不同的并发模型。 Firefox可能在一个单独的线程中运行模式对话框,允许setTimeout继续在自己的线程中运行(并在200毫秒后递增flag的值)。 Chrome可能会在与setTimeout相同的线程中运行模式对话框,从而阻止setTimeout的运行(并且不允许flag的值递增)。

答案 2 :(得分:0)

什么?你设置标志为10.你为什么期望它为0?