Javascript - Как определить, загружен ли документ (IE 7 / Firefox 3)

Я хочу вызвать функцию после загрузки документа, но документ, возможно, еще не завершил загрузку. Если он загрузился, я могу просто вызвать функцию. Если он НЕ загрузился, я могу подключить прослушиватель событий. Я не могу добавить прослушиватель событий после того, как onload уже запущен, так как он не будет вызван. Итак, как я могу проверить, загрузился ли документ? Я попробовал приведенный ниже код, но он не работает. Любые идеи?

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if (body && body.readyState == 'loaded') {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}

person Marcos    schedule 11.06.2009    source источник
comment
Я хочу вызвать функцию после загрузки документа, но документ, возможно, еще не завершил загрузку. Это не вычисляет.   -  person Richard Simões    schedule 11.06.2009
comment
Я считаю, что он имеет в виду, что он не контролирует, когда его блок кода первоначально запускается, но хочет убедиться, что DoStuffFunction () не вызывается до того, как документ завершит загрузку.   -  person Ben Blank    schedule 11.06.2009


Ответы (9)


Нет необходимости во всем кодексе, упомянутом галамбалазами. Кроссбраузерный способ сделать это на чистом JavaScript - просто протестировать document.readyState:

if (document.readyState === "complete") { init(); }

Так же и jQuery.

В зависимости от того, где загружен JavaScript, это можно сделать внутри интервала:

var readyStateCheckInterval = setInterval(function() {
    if (document.readyState === "complete") {
        clearInterval(readyStateCheckInterval);
        init();
    }
}, 10);

Фактически, document.readyState может иметь три состояния:

Возвращает «загрузка» во время загрузки документа, «интерактивный» - после завершения анализа, но все еще загружающие подресурсы, и «завершение» после загрузки. - document.readyState в сети разработчиков Mozilla

Поэтому, если вам нужна только модель DOM, проверьте document.readyState === "interactive". Если вам нужно, чтобы была готова вся страница, включая изображения, проверьте document.readyState === "complete".

person laurent    schedule 17.08.2011
comment
@costa, если document.readyState == "complete", значит все, включая изображения, загружено. - person laurent; 30.03.2013
comment
Я использую комбинацию обоих событий и document.readyState, чтобы убедиться, что функция запускается после анализа DOM или позже, в зависимости от того, когда она была вызвана. Есть ли мероприятие для интерактивного readyState? - person Tomáš Zato - Reinstate Monica; 25.11.2013
comment
Потрясающе - модель DOM обманчива. - person Yugal Jindle; 29.11.2013
comment
Я бы использовал /loaded|complete/.test(document.readyState). Некоторые браузеры устанавливают для document.readyState значение «загружено», а не «завершено». Кроме того, document.readyState НЕ гарантирует, что шрифты были загружены, нет хорошего способа проверить это без плагина. - person Ryan Taylor; 23.05.2014
comment
А что насчет document.onreadystatechange? Это кажется более оптимальным, если браузеры его поддерживают. stackoverflow.com/questions/ 807878 / - person ; 12.01.2015
comment
Я думаю, что это приведет к бесконечному циклу, если init() приведет к ошибке. @galambalazs answer позаботится об этом случае - person wpp; 20.01.2015
comment
@wpp, ты прав. На всякий случай лучше очистить интервал перед вызовом init(). Я обновил код. - person laurent; 20.01.2015
comment
Я думаю, чтобы избежать setInterval, следуйте приведенному ниже ответу. - person cantfindaname88; 01.06.2015
comment
Я думаю, было бы лучше проверить document.readyState !== "loading", состояние готовности DOM. Это предотвращает возникновение проблем, если readyState по какой-то причине проверяется поздно (после интерактивного состояния). - person rnevius; 22.09.2015

Нет необходимости в библиотеке. jQuery какое-то время использовал этот скрипт, кстати.

http://dean.edwards.name/weblog/2006/06/again/

// Dean Edwards/Matthias Miller/John Resig

function init() {
  // quit if this function has already been called
  if (arguments.callee.done) return;

  // flag this function so we don't do the same thing twice
  arguments.callee.done = true;

  // kill the timer
  if (_timer) clearInterval(_timer);

  // do stuff
};

/* for Mozilla/Opera9 */
if (document.addEventListener) {
  document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
  document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
  var script = document.getElementById("__ie_onload");
  script.onreadystatechange = function() {
    if (this.readyState == "complete") {
      init(); // call the onload handler
    }
  };
/*@end @*/

/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
  var _timer = setInterval(function() {
    if (/loaded|complete/.test(document.readyState)) {
      init(); // call the onload handler
    }
  }, 10);
}

/* for other browsers */
window.onload = init;
person gblazex    schedule 29.06.2010
comment
Именно то, что я искал - функцию jQuery.ready без библиотеки jQuery. Спасибо! - person stricjux; 14.09.2011
comment
Совершенно упустил суть вопроса. init не будет запускаться, если этот опубликованный вами код будет включен после того, как страница уже загружена, что является точкой OP: он / она не может контролировать, когда его скрипт включен. (учтите, что будет работать только ветка setInterval) - person Roatin Marth; 24.01.2012
comment
Это принадлежит библиотеке. Наряду со всеми остальными колесами люди обычно изобретают заново. - person b01; 14.05.2013

Вероятно, вы захотите использовать что-то вроде jQuery, которое упрощает программирование JS.

Что-то типа:

$(document).ready(function(){
   // Your code here
});

Казалось бы, делать то, что вам нужно.

person dan    schedule 11.06.2009
comment
И если он хочет увидеть, как jQuery делает это портативным способом, исходный код jQuery готов для проверки :-) - person Thomas L Holaday; 11.06.2009
comment
И если это неясно, если ready() вызывается после загрузки документа, переданная функция запускается немедленно. - person Ben Blank; 11.06.2009
comment
@Ben Blank: если, конечно, сам jQuery не включен после загрузки документа;) - person Roatin Marth; 24.01.2012
comment
@Roatin Marth - На самом деле, это тоже отлично работает. (Просто попробовал с jQuery 1.7.1 на FF8 и IE8.) - person Ben Blank; 24.01.2012
comment
@ Бен Бланк: Ага, смотри, я в FF 3.0, где ничего не получается. - person Roatin Marth; 24.01.2012
comment
-1: даже если ответ имеет смысл, OP никогда не упоминал jQuery. Использование всего проекта jQuery только для подготовки документа - это излишне. - person marcgg; 25.01.2013

Если вы действительно хотите, чтобы этот код запускался при load, а не в состоянии готовности (т.е. вам нужно, чтобы изображения были загружены), то, к сожалению, функция ready не сделает этого за вас. Обычно я делаю что-то вроде этого:

Включить в документ javascript (т.е. всегда вызывается перед запуском onload):

var pageisloaded=0;
window.addEvent('load',function(){
 pageisloaded=1;
});

Тогда ваш код:

if (pageisloaded) {
 DoStuffFunction();
} else {
 window.addEvent('load',DoStuffFunction);
}

(Или эквивалент в вашей структуре предпочтений.) Я использую этот код для предварительного кэширования javascript и изображений для будущих страниц. Поскольку материалы, которые я получаю, вообще не используются для этой страницы, я не хочу, чтобы они имели приоритет над быстрой загрузкой изображений.

Может быть способ получше, но я его еще не нашел.

person Nathan Stretch    schedule 21.08.2009

Mozila Firefox говорит, что onreadystatechange является альтернативой DOMContentLoaded.

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

В DOMContentLoaded документ Мозилы говорит:

Событие DOMContentLoaded запускается, когда документ был полностью загружен и проанализирован, не дожидаясь завершения загрузки таблиц стилей, изображений и подфреймов (событие загрузки можно использовать для обнаружения полностью загруженной страницы).

Я думаю, что событие load нужно использовать для полной загрузки документа + ресурсов.

person Mostafa Talebi    schedule 16.07.2014

Вышеупомянутый способ с JQuery - самый простой и наиболее часто используемый способ. Однако вы можете использовать чистый javascript, но попробуйте определить этот сценарий в голове, чтобы он читался в начале. Вы ищете window.onload событие.

Ниже приведен простой скрипт, который я создал для запуска счетчика. Затем счетчик останавливается после 10 итераций.

window.onload=function()
{
    var counter = 0;
    var interval1 = setInterval(function()
    { 
        document.getElementById("div1").textContent=counter;
        counter++; 
        if(counter==10)
        {
            clearInterval(interval1);
        }
    },1000);

}
person Talha    schedule 11.04.2012

Попробуй это:

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if ((body && body.readyState == 'loaded') || (body &&  body.readyState == 'complete') ) {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload',DoStuffFunction);
    }
}
person smit    schedule 10.12.2013

У меня есть другое решение, мое приложение нужно запускать при создании нового объекта MyApp, поэтому оно выглядит так:

function MyApp(objId){
     this.init=function(){
        //.........
     }
     this.run=function(){
          if(!document || !document.body || !window[objId]){
              window.setTimeout(objId+".run();",100);
              return;
          }
          this.init();
     };
     this.run();
}
//and i am starting it 
var app=new MyApp('app');

он работает во всех известных мне браузерах.

person vitus    schedule 05.06.2013

person    schedule
comment
Кажется, не работает в последней версии Chrome document.loaded всегда не определено - person Aniket; 22.05.2019
comment
это был 2010 год :). Теперь я буду использовать body.readyState === 'loaded' - person Jman; 22.05.2019