Chrome - проблема последовательности выполнения Javascript с alert ()

1

сегодня я задавался вопросом о последовательности выполнения в 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 не запускает предупреждение() и не ждет нажатия кнопки "ОК"?

Спасибо
Олли

Показать ещё 1 комментарий
Теги:
google-chrome

3 ответа

0
Лучший ответ

Проблема заключается в том, что 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">
0

Делая немного исследований для подобных проблем, ответ на этот вопрос, похоже, правильно:

... изменение объекта стиля запускает сообщение запроса repaint на средство визуализации страницы, и это обрабатывается, как только браузер становится бездействующим, что после завершения этой процедуры скрипта.

По-видимому, это делает только Chrome.

-1

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">
  • 0
    Ваш ответ не содержит каких-либо объяснений или комментариев относительно того, в чем заключается проблема и как ваш код ее решает. Кроме того, это по сути тот же самый и принятый ответ, который был размещен почти за 15 минут до вашего.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню