2

I am a Java developer trying to learn javascript. I have a select book dropdown from which I can select a book. On selection, I will display the following message. You have selected <selectedBook> book!

<!DOCTYPE html>
<html>
<head>
    <script>
function selectBook() {

  var selectedBook = document.getElementById("books").value;
  if (selectedBook=='select') {
    document.getElementById("displaySelectedBook").style.display = "none";
    alert("Please select a valid book");
    return;
  } 
document.getElementById("displaySelectedBook").style.display = "block";
document.getElementById("displaySelectedBook").innerHTML = "You have selected " + selectedBook.bold() + " book!";

}
</script>
</head>
<body>
<br>
<table style="width:30%" border="1" align="center">
  <tr>
    <th>Select a Book</th>
    <td>
      <select id="books" onchange="selectBook()
      ">
          <option value="select">Select</option>
          <option value="Head First Java">Head First Java</option>
          <option value="Complete Reference">Complete Reference</option>
          <option value="Gang of four">Gang of four</option>
          <option value="Effective Java">Effective Java</option>
        </select>
    </td>
  </tr>
   <tr>
  <td colspan="2" align="center" style="display: none;">
     <button type="button" onclick="selectBook()">Select!</button>
  </td>


 </tr>

</table>

<p id="displaySelectedBook"/>

</body>
</html>

The problem is when I select a valid book, say Complete Reference, and then I select "select", the expected behavior is that the para tag with ID displaySelectedBook should disappear before the alert message is displayed. But it works the other way round.

When I introduced a delay as shown below it worked fine

   setTimeout(function() {
      alert("Please select a valid book");
   }, 1);

Shouldn't the code run sequencely? Can anyone please explain the behavior here? Thanks

Andy
  • 5,433
  • 6
  • 31
  • 38
  • I tried with Firefox, and the sequence is respected. With Chrome, I experience what you describe here. I don't have an explanation, but seems related to the browser possibly. I found somebody else reporting a similar sequence issue [here](https://teamtreehouse.com/community/both-script-alert-run-before-the-html-renders-the-h1-tags-is-this-because-of-chrome). – sal Aug 11 '18 at 20:46
  • Thanks for your answer. I found the same issue in safari as well. – Andy Aug 11 '18 at 20:50
  • It's not just the style, the innerText and innerHTML do not update either. – Steven Spungin Aug 11 '18 at 20:58
  • 1
    My only thought is that on certain browsers, the DOM will not update while in an event handler do avoid UI synchronizations issues. ---- I take that back. I just put the entire handler in a setTimeout and the issue still occurs. – Steven Spungin Aug 11 '18 at 21:00
  • @steven this is still true. It does not only apply to event handlers but to every code – Jonas Wilms Aug 11 '18 at 21:04
  • When you put a breakpoint and step through in chrome, it works as expected. !? – Steven Spungin Aug 11 '18 at 21:13
  • [exact unanswered duplicate](https://stackoverflow.com/questions/41985247/why-do-dom-updates-and-alert-execute-out-of-sequence-in-chrome) – Jonas Wilms Aug 11 '18 at 21:22

1 Answers1

1

Imagine this blocking js code:

  for(let i = 0; i < 1000; i++)
    document.body.innerHTML += "something";

If the browser would directly rerender every time the DOM changes, mutating the DOM would take very long and would have a great impact on performance. Therefore most browsers just rerender after javascript stops executing. alert is actually the only way to really block javascript, so it is the only case where you can really notice this behaviour.

When I introduced a delay as shown below it worked fine

Because then JS stops executing for one tick, and the browser got some time to rerender.

Different browsers behave differently here because it is actually not specified.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151