16

In browsers that support the event DOMContentLoaded and the property document.readyState:

When DOMContentLoaded fires, can I assume that the value of document.readyState will always be either "complete" or "interactive"/"loaded"?

(Or could it be that document.readyState sometimes still has the value "loading"?)

In your answer please provide a reference to an authoritative source.

You may wonder: Why not just listen to readystatechange? It is because the Android 2.3.5 standard browser is a target platform, and it does not implement the readystatechange event.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
feklee
  • 7,555
  • 9
  • 54
  • 72
  • 2
    Why not just listen to `DOMContentLoaded`? ;-) – Marat Tanalin Nov 12 '12 at 15:44
  • 1
    I'm pretty sure Android 2.3 supports the readystatechange event, but just uses loaded instead of interactive/complete. I'll investigate and get back. – dotnetCarpenter Oct 07 '13 at 21:26
  • UPDATE - Indeed you're correct. I've made a small test here: http://test.it-kollektivet.dk/white-space/android2.3.html But the only value I get from document.readyState is **loading** and **loaded**. – dotnetCarpenter Oct 07 '13 at 21:45

3 Answers3

11

The value of the readyState property is always "interactive" when DOMContentLoaded has fired. This is evidenced by the fact that the MDN documentation claims:

// alternative to DOMContentLoaded event
document.onreadystatechange = function () {
  if (document.readyState == "interactive") {
    initApplication();
  }
}

is interchangeable with a DOMContentLoaded handler. You can also have a look at the spec here, which reiterates this.

Jeremy Wiebe
  • 3,894
  • 22
  • 31
Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
  • 4
    Unfortunately, that's not right on Android 2.3.5. I just did a test, and the result is completely unexpected to me: When `DOMContentLoaded` fires, then the value of `document.readyState` is `"loaded"` (i.e. neither `"complete"`, nor `"interactive"`, nor `"loading"`). – feklee Nov 12 '12 at 16:08
  • 1
    @feklee That must be because there are no sub resources, in which case DOMContentLoaded and the load event fire simultaneously. Have a closer look at the spec I linked. – Asad Saeeduddin Nov 12 '12 at 19:25
  • @feklee Once the load event fires it should be "complete", as in other browsers, not "loading". The sequence of values is "loading" -> "interactive" -> "complete". Guess Android isn't following the spec on this one, but to have "loading" after everything is loaded is just ridiculous. Are you sure there isn't a mistake in your test case? – Asad Saeeduddin Nov 12 '12 at 19:49
  • Sorry, that was a typo. Correct is: *Note that the value is "loaded", not "complete". Furthermore, once the "load" event fires, the value is "complete" as in other browsers.* – feklee Nov 12 '12 at 19:52
  • 3
    @feklee I was curious; this answer was not completely accurate as far as your problem was concerned. Why did you accept it? More importantly, how did you resolve the issue? Thanks – Asad Saeeduddin Nov 15 '12 at 10:00
  • Well, you pointed me to MDN saying that the above code is an ["alternative to DOMContentLoaded"](https://developer.mozilla.org/en-US/docs/DOM/document.readyState#Examples), and MDN is an authoritative source IMHO. As for the issue with Android 2.3: In my code, I simply treat `"interactive"` and `"loaded"` as identical. I've seen other code on the net doing the same (I forgot where it was, but it was in some popular project that again could be considered authoritative). – feklee Nov 15 '12 at 17:59
  • "interactive" can be setted to early in IE8/IE9 – 4esn0k Mar 04 '13 at 13:03
  • 4
    I appreciate that this is a very old answer, but there's a subtle difference that really caught me out. `readyState` is set to `interactive` *before* scripts with the `defer` attribute are evaluated, while `DOMContentLoaded` is fired *after*. – MTCoster May 10 '18 at 12:34
  • 2
    @MTCoster i am automating browser with scripts, and this comment was really helpful to figure out difference between readyState interactive and webnavigation.onDomContentLoaded. Thank you! – Fedcomp Dec 28 '19 at 13:56
  • @MTCoster That is consistent with [this](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer) documentation, i.e. that deferred scripts are guaranteed to have executed once the `DOMContentLoaded` event is dispatched. But I'm confused about how to square that with the claim [here](https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event#checking_whether_loading_is_already_complete) that you can infer that `DOMContentLoaded` has fired if `document.readyState` is not `loading` (what about `interactive`?) – user3678429 Jan 23 '22 at 00:27
  • A solution is also in this thread: https://stackoverflow.com/questions/5968300/how-do-i-fire-an-event-when-document-readystate-is-complete/73750432#73750432 – Kevin O. Sep 16 '22 at 21:25
5

As per accepted answer:

The value of the readyState property is always "interactive" when DOMContentLoaded has fired.

Wrong

It has either of:

  • interactive
  • complete

document . readyState ref.

Returns "loading" while the Document is loading, "interactive" once it is finished parsing but still loading subresources, and "complete" once it has loaded.

If one attach an event listener to readystatechange before Document has state interactive one can check for interactive alone, like with example from MDN. Then one will catch the state if it ever reaches it.

However if one check the state at a later stage it is not.

Also by example from MDN, these are equal:

document.onreadystatechange = function () {
  if (document.readyState === 'interactive') {
    initApplication();
  }
}


document.addEventListener("DOMContentLoaded", function () {
    initApplication();
});

That does not mean:

if (document.readyState !== 'loading')
    assert(document.readyState === 'interactive')

Which the answer suggests.

As to say:

  • document.addEventListener("DOMContentLoaded", ...

will never equal to:

  • window.addEventListener('load', ...
Moba
  • 159
  • 1
  • 3
1

The value of the readyState property is at least "interactive" when DOMContentLoaded is fired. As @MTCoster pointed out here, the event is deferred until linked scripts with defer attribute and module scripts, linked or inline, have executed. See also this post.

Markus
  • 668
  • 7
  • 27