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>
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.
Depending on your browser requirements you can use the async
tag and import your script after content loads. This probably accomplishes the same thing as setTimeout(func, 0)
, but perhaps it's a little less hacky.
See http://plnkr.co/edit/7DlNWNHnyX5s6UE8AFiU?p=preview
html:
...
<body>
<h1 id="main">Hello Plunker!</h1>
<script async src="script.js"></script>
</body>
...
script.js:
for(var i=0; i<500; ++i) {
document.getElementById('main').innerText += new Date();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With