3

What's the logic behind order of JS code execution? I'd expect after clicking the button the background to become red and THEN the message to show up. However, the message is appearing first and color is applied to background after I click OK -> CodePen. What would be proper&correct way to make the background red BEFORE I click OK?

function run(){
  document.body.style.backgroundColor = 'red';
  alert('Contratulations!');
}
<html>
<head></head>
<body>
  <button onclick="run()">Click me!</button>
</body>
</html>
oboer
  • 157
  • 1
  • 1
  • 13

3 Answers3

4

The code is executed in the order you expect, however, each of those statements is not synchronous, as they invoke funcitonality provided by the Webbrowser.

Browser executed Javascript does not occur on the UI Thread. So when you change the DOM (the abstraction that allow Javascript to interact with browser HTML), it instead triggers an update to the UI (Browser page) which occurs separate from javascript execution. The underlying DOM element is updated, but there is a non instantaneous update to the actual UI.

In your code, after you change the DOM element, the code then immediately triggers the browser to display an Alert. Displaying alerts is a browser specific behavior, and in the case of Chrome, it pauses the UI update, and requires you to interact with the alert before continuing. In Firefox, the Alert is shown after the UI is updated.

The behavior between the two browsers is simply a difference in how the browser rendering engine and event loops are implemented.

function run(){
  document.body.style.backgroundColor = 'red';
  setTimeout(function() {
    alert('Contratulations!');
  },0 );
}
<html>
<head></head>
<body>
  <button onclick="run()">Click me!</button>
</body>
</html>

This answer has a little more information on how you can solve the problem, Why is setTimeout(fn, 0) sometimes useful?

By calling setTimeout you are adding the alert display to the end of the javascript event loop, which gives the UI enough time to update.

Community
  • 1
  • 1
Alan
  • 45,915
  • 17
  • 113
  • 134
1

This is being caused by the fact that the alert() call is a call to a modal dialog. A modal dialog is one that blocks the UI from doing anything else until the dialog is closed. This is simply a matter of the browser not rendering the color fast enough to show it before the JavaScript runtime moves on to the next statement. It's important to recognize that alert() is actually a method of the window object. You could have written window.alert(). Knowing this you must then understand that the window object is not a native part of the JavaScript language. window is a browser object and, as such, is managed by the browser, not the JavaScript runtime.

I have modified your code to show the message in the console, rather than an alert. Because writing to the console is non-UI-blocking, you see the color change immediately.

function run(){
  document.body.style.backgroundColor = 'red';
  console.log('Contratulations!');
}
<html>
<head></head>
<body>
  <button onclick="run()">Click me!</button>
</body>
</html>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

Try this.

function run(){
  document.body.style.backgroundColor = 'red';
  setTimeout(function() {
    alert('Contratulations!');
  }, 0);
}
<html>
<head></head>
<body>
  <button onclick="run()">Click me!</button>
</body>
</html>

setTimeout calls a function after a delay. In this case, the delay is zero, allowing the background to change before creating the alert, but not creating any noticeable delay.

afuous
  • 1,478
  • 10
  • 12