сегодня я задавался вопросом о последовательности выполнения в Chrome для JavaScript-функции "alert()"
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test1">
test1 test1 test1 test1
</div>
<div id="test2">
test2 test2 test2 test2
</div>
<input type="button" onclick="runTest()" value="start test">
<script>
function runTest()
{
$('#test1').css('background-color', 'red');
alert('test1');
$('#test2').css('background-color', 'red');
alert('test2');
}
</script>
В Firefox 62 и IE11 (работает, как и ожидалось):
1) BGcolor Line 1
2) Alertbox 1
3) (click OK)
4) BGcolor Line 2
5) Alertbox 2
6) (click OK)
В Chrome 69.0.3497.100:
1) Alertbox 1
2) (click OK)
3) Alertbox 2
4) (click OK)
5) BGcolor Line 1
6) BGcolor Line 2
Почему Chrome не запускает предупреждение() и не ждет нажатия кнопки "ОК"?
Спасибо
Олли
Проблема заключается в том, что alert()
выводится программным обеспечением браузера, а не средой выполнения JavaScript или механизмом рендеринга CSS, и часто браузер может работать быстрее/медленнее, чем позволяет время выполнения JavaScript. В этом случае alert
выводится до того, как среда выполнения JavaScript и механизм рендеринга CSS могут изменить цвет фона. И поскольку alert()
является модальным диалогом, остальная часть пользовательского интерфейса блокируется до тех пор, пока alert()
будет закрыто, поэтому до этого вы не увидите красного фона.
Решение этой проблемы заключается в том, чтобы вручную взять на себя alert()
, отложив его до тех пор, пока текущая функция не завершится таймером:
function runTest() {
$('#test1').css('background-color', 'red');
// Timer callback functions are placed in the event queue and
// won't run until the JavaScript call stack is idle. So,
// makeAlert("test1") won't run until after runTest(), which
// will allow the browser to color the background red before
// the first alert is rendered.
setTimeout(function(){
makeAlert("test1");
}, 100);
}
function makeAlert(msg){
// Now, the first background has been applied and so
// we can ask for the first alert().
alert(msg);
// Now, we'll set the second background color
$('#test2').css('background-color', 'red');
// And defer the second alert until after this function
// is complete.
setTimeout(function(){
alert("test2");
}, 100);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test1">test1 test1 test1 test1</div>
<div id="test2">test2 test2 test2 test2</div>
<input type="button" onclick="runTest()" value="start test">
Делая немного исследований для подобных проблем, ответ на этот вопрос, похоже, правильно:
... изменение объекта стиля запускает сообщение запроса repaint на средство визуализации страницы, и это обрабатывается, как только браузер становится бездействующим, что после завершения этой процедуры скрипта.
По-видимому, это делает только Chrome.
function runTest() {
setTimeout(function() {
var a = document.querySelector('#test1');
a.style.backgroundColor = 'red';
alert('test1');
}, 100);
setTimeout(function() {
var a = document.querySelector('#test2');
a.style.backgroundColor = 'red';
alert('test2');
}, 200);
}
<div id="test1">
test1 test1 test1 test1
</div>
<div id="test2">
test2 test2 test2 test2
</div>
<input type="button" onclick="runTest()" value="start test">