Friday, February 15th, 2008

Using setTimeout to Solve DOMContentLoaded?

Category: JavaScript

Stuart Colville was reading the following info on setTimeout() from JavaScript the Definitive Guide:

“In practice, setTimeout() tells the browser to invoke the function when it has finished running the event handlers for any currently pending events and has finished updated the current state of the document”

He then thought, does setTimeout solve the DOMContentLoaded problem?.

He tested this hypothesis with a simple function that uses DOMContentLoaded for Mozilla and Opera, else uses setTimeout:


  1. function DOMReady(f){
  2.   if (/(?!.*?compatible|.*?webkit)^mozilla|opera/i.test(navigator.userAgent)){ // Feeling dirty yet?
  3.     document.addEventListener("DOMContentLoaded", f, false);
  4.   }  else {
  5.     window.setTimeout(f,0);
  6.   }
  7. }

Jonathan Snook ran with this and found that it works until gzip gets into the picture:

If you could guarantee that the file would be sent via gzip compression every time then yes, using setTimeout could potentially be a viable way to mimic DOMContentLoaded. In fact, you could forego using DOMContentLoaded at all and simply rely on setTimeout for all browsers. window.setTimeout could be the new window.onload.

In a related note, I recently saw some benchmarks showing that setTimeout(…, 0) may take longer than you think to run.

Posted by Dion Almaer at 8:13 am

3.5 rating from 23 votes


Comments feed TrackBack URI

I just posted this comment on (but it’s still waiting moderation). There’s another problem with using setTimeout – it will fire early if you have slow external scripts on your page.

I’ve put together a simple test that loads an external script which sleeps for a few seconds before responding. The result, in IE7 + Safari is the setTimeout fires before the DOM is actually ready.

So I think if you are going to consider using setTimeout as your DOM ready function, you need to be very sure of the make up of your page, i.e. gzip & no external scripts. This sounds fine for smaller projects, but doesn’t work so well for companies relying on ads served through JavaScript for some revenue.

Comment by remy — February 15, 2008

Man, jQuery is doing the same.

// Remove event listener to avoid memory leak
if ( jQuery.browser.mozilla || jQuery.browser.opera )
document.removeEventListener( “DOMContentLoaded”, jQuery.ready, false );

// Remove script element used by IE hack
if( !window.frames.length ) // don’t remove if frames are present (#1187)
jQuery(window).load(function(){ jQuery(“#__ie_init”).remove(); });

Comment by bollywood — February 15, 2008

What ever happened to just putting a script tag at the bottom of your page and firing your own custom event. I can’t think of an easier more widely supported method.

Comment by benyc — February 15, 2008

@benyc : that is the way you often do it in real life. However, people that create JS libraries have a self imposed limit that all you have to do is include the single tag, which is easier for adoption of the library.

Comment by Steve Roussey — February 15, 2008

Using the bottom script is too late. If an HTML page stalls half way through the load then it part of it is visible but the elements are not enlivened with the unobtrusive event handlers.

Comment by PeterMichaux — February 16, 2008

What about

function try_again(){
else{setTimeout(try_again, 1000);}

Comment by Mikael Bergkvist — February 16, 2008

Good suggestion from Peter tbh.
function try_again(){
else{setTimeout(try_again, 1000);}
Though instead of 1 second, I’d set the timeout on 0.
All browsers have a minimum setTimout timer, which lies between 20ms (fastest afaik) and 75ms (slowest), which should provide nearly the same error margin as other domready methods crossbrowser, though other methods will probably be more accurate for specific browsers.

Comment by Ben — February 18, 2008

Leave a comment

You must be logged in to post a comment.