Why does the timeout fire before the “click” event loop is complete on Firefox?

Steps:

  1. run code in the Firefox
  2. wait 5 seconds (important!)
  3. Press OK or Cancel
  4. expect flag == 0, but it is 10.
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;
   
                          
<button type="button" id="button">Click Me!</button>

  • Knockout click binding with javascript confirm
  • Javascript confirm with PHP function afterward
  • Javascript - rename confirm() buttons
  • Are custom buttons possible in an alert box?
  • CakePHP Javascript Confirm dialog Form Submission cancel not working
  • Javascript confirm dialog and middle/right mouse click
  • How to pass a parameter in a Javascript confirm function?
  • Custom confirm dialog with JavaScript
  • “Confirm navigation” alertbox
  • HTML Form submission with javascript confirm delays on Google Chrome
  • Javascript - How many arguments are there for confirm?
  • Form confirmation on submit
  • 3 Solutions collect form web for “Why does the timeout fire before the “click” event loop is complete on Firefox?”

    Because unlike many browsers, Firefox may allow the JavaScript thread to run other code while the alert, prompt, and confirm modals are showing, suspending the current code. (See end of answer for more on about the “may” in that sentence.) The task where the alert etc. was called is suspended, so the code in that task doesn’t proceed, but other tasks are allowed to run.

    This means

    • Timers can get their callback

    • Ajax completion handlers can run

    • Etc.

    There’s never JavaScript running concurrently in two places, but Firefox does let the thread run other tasks while a task is suspended by those modals.

    It’s an Firefox quirk. I first learned about it right here on Stack Overflow, thanks to bobince.


    Why I said “may” allow the JavaScript thread to run: It used to be fairly reliable (olders versions of Firefox). I had no trouble replicating it on Firefox 29 or 38. Firefox 42 seems to make it much less likely, but it does still happen.

    I would expect (though I could be wrong) that Mozilla will change this to be in line with other browsers, as one could argue it violates JavaScript’s run-to-completion semantics for tasks, and those semantics just got beefed up and clarified by the latest specification.

    I tried this in both Firefox and in Chrome. In Firefox I got 10 for a result. In Chrome I got 0 for a result. Likely Firefox and Chrome have different concurrency models when it comes to the confirm function. Firefox is likely running the modal dialog in a separate thread, allowing the setTimeout to continue to run in its own thread (and incrementing the value of flag after 200 milliseconds). Chrome is likely running the modal dialog in the same thread as setTimeout, thus blocking the running of the setTimeout (and not allowing the value of flag to be incremented).

    What? You set flag to 10. Why would you expect it to be 0?