Почему этот код на основе setTimeout не работает в Firefox с небольшим таймаутом (работает в Internet Explorer / Chrome)?

У меня есть следующий код, который демонстрирует разницу в вызове долго выполняющейся функции непосредственно из триггера события, по сравнению с использованиемsetTimeout().

Намеренное поведение:

Когда первая кнопка нажата, она кажется нажатой, вычисление выполняется в течение нескольких секунд, затем, когда вычисление заканчивается, кнопка снова нажимается, и второй столбец изменяется с «еще не вычисляется» на «вычисление выполнено». (Я не буду подробно останавливаться на том, почему это должно происходить;это объясняется в связанном ответе.)

Когда вторая кнопка нажата, кнопка нажимается немедленно; второй столбец сразу меняется на «вычисление ...» текста. Когда вычисление заканчивается через несколько секунд, второй столбец меняется с «вычисление ...» на «вычисление выполнено».

Что на самом деле происходит:

Это отлично работает в Chrome (обе кнопки ведут себя как положено)

Это прекрасно работает вInternet Explorer 8

Это НЕ работает в Firefox (v.25) как есть. В частности, вторая кнопка ведет себя на 100% как первая.

Изменение таймаута вsetTimeout() из0 в1 не имеет никакого эффекта

Изменение таймаута вsetTimeout() из0 в500 работает

Что оставляет меня с большой загадкой.

По всей причине, почемуsetTimeout() работает, в то время как отсутствие одного не делает, задержка должна иметь нулевой эффект на то, как все работает,посколькуsetTimeout()Основная цель - изменить порядок очередей здесь, а не откладывать.

Итак, почему он не работает с задержкой 0 или 1 в Firefox, но работает как ожидается с задержкой 500 (и работает с любой задержкой в Internet Explorer 8 / Chrome)?

ОБНОВЛЕНИЕ: в дополнение к исходному коду ниже, я также сделалJSFiddle, Но по какой-то причине JSFiddle отказывается даже загружать мой Internet Explorer 8, поэтому для этого тестирования требуется приведенный ниже код.

ОБНОВЛЕНИЕ 2: Кто-то поднял вопрос о возможной проблеме с настройкой конфигурацииdom.min_timeout_value в Firefox. Я отредактировал его с 4 до 0, перезапустил браузер, и ничего не было исправлено. Он все еще терпит неудачу с таймаутом 0 или 1 и успешно с 500.

Вот мой исходный код - я просто сохранил его в HTML-файл на диске C: и открыл во всех трех браузерах:

<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>

Для тестирования вам нужно изменить границы вложенного цикла на 300/100/100 для Internet Explorer 8; или 1000/1000/500 для Chrome из-за различной чувствительности ошибки «этот JS занимает слишком много времени» в сочетании с частотой вращения движка JavaScript.

Ответы на вопрос(3)

Ваш ответ на вопрос