Dlaczego ten kod oparty na setTimeout nie działa w Firefoksie z małym limitem czasu (działa w przeglądarce Internet Explorer / Chrome)?

Mam następujący kod, który pokazuje różnicę w wywoływaniu długo działającej funkcji bezpośrednio z wyzwalacza zdarzenia, a nie z użyciemsetTimeout().

Zamierzone zachowanie:

Po naciśnięciu pierwszego przycisku wydaje się on być wciśnięty, obliczenia trwają przez kilka sekund, a po zakończeniu obliczeń przycisk pojawia się ponownie wciśnięty, a druga kolumna zmienia się z „nie obliczając jeszcze” na „obliczenia wykonane”. (Nie będę wyjaśniał, dlaczego tak się dzieje;jest to wyjaśnione w powiązanej odpowiedzi.)

Po naciśnięciu drugiego przycisku przycisk natychmiast naciska; druga kolumna natychmiast zmienia się na tekst „obliczanie ...”. Gdy obliczenie zakończy się kilka sekund później, druga kolumna zmieni się z „obliczania ...” na „obliczenia wykonane”.

Co właściwie się dzieje:

Działa to doskonale w Chrome (oba przyciski zachowują się zgodnie z oczekiwaniami)

To działa idealnie wInternet Explorer 8

To nie działa w Firefoksie (wersja 25) jak jest. W szczególności drugi przycisk zachowuje się w 100% jako pierwszy.

Zmiana limitu czasu wsetTimeout() z0 do1 nie działa

Zmiana limitu czasu wsetTimeout() z0 do500 Prace

Co pozostawia mnie z wielką zagadką.

Zgodnie z całym powodem dlaczegosetTimeout() działa, podczas gdy brak jednego nie, opóźnienie powinno mieć zerowy wpływ na to, jak wszystko działa,odsetTimeout()Głównym celem jest tutaj zmiana kolejności kolejkowania, NIE opóźnianie rzeczy.

Dlaczego więc nie działa z opóźnieniem 0 lub 1 w Firefoksie, ale działa zgodnie z oczekiwaniami z opóźnieniem 500 (i działa z dowolnym opóźnieniem w Internet Explorerze 8 / Chrome)?

AKTUALIZACJA: Oprócz kodu źródłowego poniżej zrobiłem teżJSFiddle. Ale z jakiegoś powodu JSFiddle odmawia nawet załadowania mojego Internet Explorera 8, więc do tego testu wymagany jest poniższy kod.

UPDATE2: Ktoś podniósł możliwość wystąpienia problemu z ustawieniem konfiguracjidom.min_timeout_value w Firefoksie. Zmodyfikowałem go z 4 na 0, uruchomiłem ponownie przeglądarkę i nic nie zostało naprawione. Nadal kończy się niepowodzeniem z limitem czasu 0 lub 1 i kończy się wynikiem 500.

Oto mój kod źródłowy - po prostu zapisałem go w pliku HTML na dysku C: i otworzyłem we wszystkich trzech przeglądarkach:

<html><body>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>

<table border=1>
    <tr><td><button id='do'>Do long calc - bad status!</button></td>
        <td><div id='status'>Not Calculating yet.</div></td></tr>
    <tr><td><button id='do_ok'>Do long calc - good status!</button></td>
        <td><div id='status_ok'>Not Calculating yet.</div></td></tr>
</table>

<script>
function long_running(status_div) {
    var result = 0;
    for (var i = 0; i < 1000; i++) {
        for (var j = 0; j < 700; j++) {
            for (var k = 0; k < 200; k++) {
                result = result + i + j + k;
            }
        }
    }
    $(status_div).text('calclation done');
}

// Assign events to buttons
$('#do').on('click', function () {
    $('#status').text('calculating....');
    long_running('#status');
});
$('#do_ok').on('click', function () {
    $('#status_ok').text('calculating....');
    window.setTimeout(function (){ long_running('#status_ok') }, 0);
});
</script>
</body></html>

Aby przetestować, będziesz musiał zmienić granice zagnieżdżonej pętli na 300/100/100 dla Internet Explorera 8; lub do 1000/1000/500 dla Chrome, z powodu różnej czułości błędu „ten JS bierze za długo” w połączeniu z prędkością silnika JavaScript.

questionAnswers(3)

yourAnswerToTheQuestion