Почему этот код на основе 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.