У меня есть следующий код, который демонстрирует разницу в вызове долговременной функции непосредственно из триггера события, а не с помощью 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)?
UPDATE: В дополнение к исходному коду ниже я также сделал JSFiddle. Но по какой-то причине JSFiddle отказывается даже загружать мой Internet Explorer 8, поэтому для этого тестирования требуется следующий код.
UPDATE2: Кто-то поднял возможность возникновения проблемы с настройкой конфигурации 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.