Matthew James Davis Matthew James Davis - 1 year ago 86
Javascript Question

Execute javascript after page load is complete

I have an html page with some pre-rendered content and some yet un-rendered content. I want to display the pre-rendered content immediately, and then begin rendering the rest of the content. I am not using jQuery.

See the following snippet. I have tried this various ways, including injecting my script before the closing body tag and providing my script to populate the DOM as a callback to

window.onload
,
document.body.onload
, and
document.addEventListener('DOMContentLoaded')
. In every case, the page does not display the pre-rendered content until the rest of the content is rendered.



<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
for (var i = 0; i < 500; i++)
main.innerText += new Date();
</script>
</body>
</html>







<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
document.body.onload = function() {
for (var i = 0; i < 500; i++)
main.innerText += new Date();
};
</script>
</body>
</html>







<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
window.onload = function() {
for (var i = 0; i < 500; i++)
main.innerText += new Date();
};
</script>
</body>
</html>







<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
document.addEventListener('DOMContentLoaded', function() {
for (var i = 0; i < 500; i++)
main.innerText += new Date();
});
</script>
</body>
</html>





One case that has worked is
window.setTimeout
with 0 timeout. However, this simply defers the function until there is nothing left to do. Is this the best practice, here?



<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
window.setTimeout(function() {
for (var i = 0; i < 500; i++)
main.innerText += new Date();
}, 0);
</script>
</body>
</html>




Answer Source

In terms of a best practice, there isn't one. In terms of a good, common, and acceptable practices, there are a handful. You've hit one:

setTimeout(function() { }, 1);

In this case, the function is executed within the browser's minimum timeout period after all other in-line processing ends.

Similarly, if you want to ensure your function runs shortly after some condition is true, use an interval:

var readyCheck = setInterval(function() {
  if (readyCondition) {
    /* do stuff */
    clearInterval(readyCheck);
  }
}, 1);

I've been using a similar, but more generalized solution in my own work. I define a helper function in the header:

var upon = function(test, fn) {
    if (typeof(test) == 'function' && test()) {
        fn();
    } else if (typeof(test) == 'string' && window[test]) {
        fn();
    } else {
        setTimeout(function() { upon(test, fn); }, 50);
    }
}; // upon()

... and I trigger other functionality when dependencies are resolved:

upon(function() { return MyNS.Thingy; }, function() {
  //  stuff that depends on MyNS.Thingy
});

upon(function() { return document.readyState == 'complete';}, function() {
  // stuff that depends on a fully rendered document
});

Or, if you want a more authoritative good practice, follow Google's example. Create an external async script and inject it before your first header script:

var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true;
s.src = '/path/to/script.js';
var header_scripts = document.getElementsByTagName('script')[0];
header_scripts.parentNode.insertBefore(s, header_scripts);

Google's solution theoretically works on all browsers (IE < 10?) to get an external script executing as soon as possible without interfering with document loading.

If you want an authoritative common practice, check the source for jQuery's onready solution.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download