6

Consider the following code:

<head>
 <style>
 .box{
   background-color:red;
   height:150px;    
   width:150px;
 }
 </style>
</head>
<body>
  <div class="box"></div> 

  <script>
  var start = new Date();
  while(true) { 
   var now = new Date(); 
   if (now-start > 10000) 
     break; 
  }
  console.log('main thread finished');
  </script>
</body>

It is a big surprise to me that DOM defers its loading for ten seconds (.box rectangle is appeared after 10 seconds!). Since it comes first ( <div class="box"></div> ), why is waiting for the script which follows? Any reasonable explanation?

Thank you

Rayon
  • 36,219
  • 4
  • 49
  • 76
Unknown developer
  • 5,414
  • 13
  • 52
  • 100
  • Excuse me @Rayon; however, after your edits it is not apparent that script comes after DOM! In that case, my question has no meaning... – Unknown developer Feb 19 '16 at 08:07
  • If you execute this snippet, you will see the same results..Placement of the script does not make any difference in this case... – Rayon Feb 19 '16 at 08:10
  • it doesnt makes any difference, whether you put in body or head. Execution halts anyway. – Shaminder Singh Feb 19 '16 at 08:12
  • Okay, but it is not comprehensible what exactly I mean if someone does not see the order code I describe... – Unknown developer Feb 19 '16 at 08:13
  • 1
    "Scripts without async or defer attributes, as well as inline scripts, are fetched and executed immediately, before the browser continues to parse the page." https://developer.mozilla.org/en/docs/Web/HTML/Element/script So your script stops parsing for 10 seconds. Not to speak about rendering the page. – Yury Tarabanko Feb 19 '16 at 08:21
  • @YuryTarabanko your comment should be the answer for this question!!! (just made it into an answer, man) – Linh Pham Feb 19 '16 at 08:33
  • @YuryTarabanko if scripts are executed immediately before the browser continues to parse the page, what do we have to say in case there is something like that inside the script: `$('.box').css(...);` which is executed normally? I mean that script knows about .box whereas the DOM part is not parsed!! It does not make sense... – Unknown developer Feb 19 '16 at 08:39
  • The browser decides NOT to render the page while the Javascript is running because the Javascript may be making changes to the page. It doesn't have to do it that way, but that is how it seems to be implemented. The page redraws when Javascript has finished executing. The same is true of Javascript running from event handlers. – jfriend00 Feb 19 '16 at 08:40
  • @ILIAS `$('.box')` will look for elements having `.box` class inside the DOM structure that has been *already parsed*. If you put more `div.box` after the script tag it wont be affected. For example https://jsfiddle.net/tarabyte/fhzmbLLh/ – Yury Tarabanko Feb 19 '16 at 09:30

5 Answers5

2

"Scripts without async or defer attributes, as well as inline scripts, are fetched and executed immediately, before the browser continues to parse the page." -- from MDN.

So your script stops parsing for 10 seconds. Not to speak about rendering the page. Basically this was done to support immediate html modifications from within the executing script. For example if your script calls for document.write('More html') it will affect parsing.

By the way executing script has access to the DOM structure that has been already parsed. Consider the following example.

<div class="box">Affected</div>
<script>
 [].forEach.call(document.querySelectorAll('.box'), function(box){
       box.innerText += '... modified';
    });
</script>
<div class="box">Not</div>
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
1

To simplify it, JavaScript is single-threaded which means it cannot take care of the DOM model at the same time as taking care of your tiny script. It goes one after another one.

Really comprehensive exmplatantion can be found here.

To avoid the problem of blocked UI, you may be interested in learning about Web Workers.

Community
  • 1
  • 1
Anton
  • 2,458
  • 2
  • 18
  • 30
  • 1
    If it is going one after another then element should get painted first before executing while loop..makes sense ? – Rayon Feb 19 '16 at 08:16
  • @RayonDabre, well, I meant it cannot be done simultaneously, however I am not sure when exactly DOM processing starts (maybe only after the closing ` – Anton Feb 19 '16 at 08:19
  • @RayonDabre, anyway, please see my updated answer, you may use web workers to process some stuff in the background. – Anton Feb 19 '16 at 08:20
1

Because of the way the engine works (single thread) any script execution blocks any progressive rendering in the page below the script

enter image description here

Sagi
  • 8,972
  • 3
  • 33
  • 41
0

This scrip does not wait for page to fully load before it starts. So this is why you wait 10 seconds. This is why such code is usually wrapped by window.onload or $(document).ready().

S. Nadezhnyy
  • 582
  • 2
  • 6
0

According to standards browser can render that element before script execution. But it doen't mean it must. I checked your code in 4 browsers and only one of them have drawn the .box before script execution - it was Opera 12. All other browsers - Chrome, FF, IE11 didn't.

As I remember, sometime chrome said that it allows them to optimize something, and they thought that internet speed became big enough to wait until full loading.

Qwertiy
  • 19,681
  • 15
  • 61
  • 128