0

I am trying to better understand the relationship between how JavaScript updates DOM object. Here is my html file index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
  </head>
  <body>
    <div id="container">old</div>
  </body>
  <script src="script.js"></script>
</html>

and here is my JavaScript file script.js,

const container = document.getElementById("container");
console.log(container, container.innerHTML);
container.innerHTML = "new";
console.log(container, container.innerHTML);

The console logs the same <div> tag but with different innerHTML which is quiet unexpected:

<div id="container">new</div> 'old'
<div id="container">new</div> 'new'

Therefore my 1st question is, what makes it possible for the console to print the same div elements but different innerHTML?


Secondly I made a small change to my script with setTimeout,

let timeout = 30;
setTimeout(() => {
  container.innerHTML = "new";
  console.log(container, container.innerHTML);
}, timeout);

Though container.innerHTML are always printed with different value, as expected, I found out that if the timeout value is above 35. The div tag is almost certainly printed differently with,

<div id="container">old</div> 'old'
<div id="container">new</div> 'new'

Then something I don't understand happens. When timeout is set below 10, it is almost certain that div tag are printed as,

<div id="container">new</div> 'old'
<div id="container">new</div> 'new'

When timeout is set somewhere between 10 and 30ish, the result toggles, meaning sometimes

<div id="container">new</div> 'old'
<div id="container">new</div> 'new'

and sometimes

<div id="container">old</div> 'old'
<div id="container">new</div> 'new'

Therefore my second question is, what causes this difference?

Much Appreciated.

bugvvd
  • 1
  • 1
  • [The console is asynchronous](https://stackoverflow.com/questions/23392111/console-log-async-or-sync). – Teemu May 27 '22 at 04:54

1 Answers1

0

Hopefully, I can respond to both questions with this:

Note that the innerHTML property is synchronous, meaning that the next line should not execute until that process finishes. However, the actual DOM must render again, and this happens separately (or asynchronously). The visual rendering in the DOM is not happening until after your stack of functions in JavaScript completes. Thus, your console.log() commands are retrieving information before the DOM has rendered with new HTML code.

You are seeing this with what you've shown in your second question. When you use a setTimeout() between 10 and 30ms, sometimes the DOM rendered again quick enough for your console.log() to now execute on the updated innerHTML. Of course, program and function execution across programming never completes at the exact same times for all kinds of reasons.

This thread may help you in understanding.

  • innerHTML also triggers a page reflow, so it may not be finished with the reflow with 1/100 of a second. innerHTML also does some extra work of parsing the html, if any. Did you try this with textContent and get the same results? – Charles Owen May 27 '22 at 05:31
  • @CharlesOwen Hi, just did the test. Substituting `container.innerHTML` with `container.textContent` records similar behavior. – bugvvd May 27 '22 at 06:31
  • Thank you for responding. I still can't get my head around. Per "...console.log() commands are retrieving information before the DOM has rendered with new HTML code", shouldn't the second console.log print the "old
    " element which is `
    old
    'old'` instead of `
    new
    'old'`?
    – bugvvd May 27 '22 at 06:35