Загрузить асинхронный код javascript, затем проверить DOM загружается перед выполнением обратного вызова

Проблема:
Загружать файлы js асинхронно, затем проверять, загружается ли dom, прежде чем будет выполнен обратный вызов от загрузки файлов.

править: Мы не используем jQuery; мы используем Prototype.
edit: добавил больше комментариев к примеру кода.

Привет, ребята,

Я пытаюсь загрузить все свои js-файлы асинхронно, чтобы они не блокировали остальную часть страницы. Но когда загружаются скрипты и вызывается обратный вызов, мне нужно знать, загружена ли DOM или нет, поэтому я знаю, как структурировать обратный вызов. См. Ниже:

//load asynchronously
(function(){
        var e = document.createElement('script'); 
        e.type = "text/javascript";
        e.async = true;
        e.src = srcstr; 
        // a little magic to make the callback happen
        if(navigator.userAgent.indexOf("Opera")){
            e.text = "initPage();";
        }else if(navigator.userAgent.indexOf("MSIE")){
            e.onreadystatechange = initPage;
        }else{
            e.innerHTML = "initPage();";
        }
        // attach the file to the document
        document.getElementsByTagName('head')[0].appendChild(e);
})();

initPageHelper = function(){ 
    //requires DOM be loaded
}

initPage = function(){
    if(domLoaded){ // if dom is already loaded, just call the function
        initPageHelper();
    }else{ //if dom is not loaded, attach the function to be run when it does load
        document.observe("dom:loaded", initPageHelper);
    }
}

Обратный вызов вызывается правильно из-за некоторой закулисной магии, о которой вы можете узнать из этого выступления Google: http://www.youtube.com/watch?v=52gL93S3usU&feature=related

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



И на самом деле, в моем коде я минимизировал два файла выше и объединил их в один файл, чтобы минимизировать время передачи и HTTP-запросы.

Затем я определяю, что я хочу запустить при загрузке DOM, и затем вызываю функцию для загрузки других сценариев.



Аналогичным образом, приведенные выше запросы фактически сжимаются в один httpRequest с помощью минификатора. Здесь они оставлены отдельно для удобства чтения. Внизу поста есть отрывок, показывающий, как выглядит код с минификатором.

Код asyncLoader.js следующий:

/**
 * Allows you to load js files asynchronously, with a callback that can be 
 * called immediately after the script loads, OR after the script loads and 
 * after the DOM is loaded. 
 * 
 * Prototype.js must be loaded first. 
 * 
 * For best results, create a regular script tag that calls a minified, combined
 * file that contains Prototype.js, and this file. Then all subsequent scripts
 * should be loaded using this function. 
 * 
 */
var onload_queue = [];
var dom_loaded = false;
function loadScriptAsync(src, callback, run_immediately) {
      var script = document.createElement('script'); 
      script.type = "text/javascript";
      script.async = true;
      script.src = src;
      if("undefined" != typeof callback){
          script.onload = function() {
                if (dom_loaded || run_immediately) 
                  callback();
                else 
                  onload_queue.push(callback);
                // clean up for IE and Opera
                script.onload = null;
                script.onreadystatechange = null;
          };

          script.onreadystatechange = function() {
            if (script.readyState == 'complete'){
                if (dom_loaded || run_immediately) 
                  callback();
                else 
                  onload_queue.push(callback);
                // clean up for IE and Opera
                script.onload = null;
                script.onreadystatechange = null;
            }else if(script.readyState == 'loaded'){
                eval(script);
                 if (dom_loaded || run_immediately) 
                      callback();
                else 
                  onload_queue.push(callback);
                // clean up for IE and Opera
                script.onload = null;
                script.onreadystatechange = null;
            }
          };
      }
      var head = document.getElementsByTagName('head')[0];
      head.appendChild(script);
}
document.observe("dom:loaded", function(){
    dom_loaded = true;
    var len = onload_queue.length;
    for (var i = 0; i < len; i++) {
        onload_queue[i]();
    }
    onload_queue = null;
});

Я добавил возможность немедленного запуска сценария, если у вас есть сценарии, которые не полагаются на полную загрузку DOM страницы. -K

10
задан Rob W 29 December 2011 в 14:20
поделиться