加载JavaScript的异步,然后检查DOM执行回调之前加载 [英] Load javascript async, then check DOM loaded before executing callback

查看:264
本文介绍了加载JavaScript的异步,然后检查DOM执行回调之前加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:结果
加载JS文件异步,然后检查,看是否DOM是从加载文件执行回调之前加载。

Problem:
Load js files asynchronously, then check to see if the dom is loaded before the callback from loading the files is executed.

编辑::我们不使用jQuery;我们使用原型。结果
修改添加更多评论到code例子。

edit: We do not use jQuery; we use Prototype.
edit: added more comments to the code example.

我试图加载我所有的js文件异步方式,从而阻塞了页面的其余部分保持它们。但是,当脚本加载和回调是所谓的,我需要知道,如果DOM已加载与否,所以我知道如何构建回调。见下图:

I'm trying to load all of my js files asynchronously so as to keep them from blocking the rest of the page. But when the scripts load and the callback is called, I need to know if the DOM has been loaded or not, so I know how to structure the callback. See below:

//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);
    }
}

回调才能正确称为由于你可以了解从这个谷歌谈幕后一些魔法:的 http://www.youtube.com/watch?v=52gL93S3usU&feature=related

什么是最简单的,跨浏览器的方法,询问是否DOM已经加载?

What's the easiest, cross-browser method for asking if the DOM has loaded already?

修改结果
下面是完整的解决方案,我就去了。结果
我包括原型,并使用正常方法异步脚本加载器。生命是与原型只是这么容易得多,所以我愿意阻止该脚本。

EDIT
Here's the full solution I went with.
I included prototype and the asynchronous script loader using the normal method. Life is just so much easier with prototype, so I'm willing to block for that script.

<script type="text/javascript" src="prototype/prototype.js"></script>
<script type="text/javascript" src="asyncLoader.js"></script>

而实际上,在我的code我缩小的两个文件上面,并把它们合并成一个文件,以减少传输时间和HTTP请求。

And actually, in my code I minified the two files above and put them together into one file to minimize transfer time and http requests.

然后我确定我要当DOM加载运行,然后调用函数加载其他脚本什么。

Then I define what I want to run when the DOM loads, and then call the function to load the other scripts.

<script type="text/javascript">
    initPage = function(){
    ...
    }
</script>
<script type="text/javascript">
    loadScriptAsync("scriptaculous/scriptaculous.js", initPage);
    loadScriptAsync("scriptaculous/effects.js", initPage);
    loadScriptAsync("scriptaculous/controls.js", initPage);
        ...
    loadScriptAsync("mypage.js", initPage);
</script>

同样,上述的要求实际上是COM pressed成一个HTT prequest使用minifier。他们留给单独这里可读性。有一个在这个帖子显示code是什么样子的minifier底部的片段。

Likewise, the requests above are actually compressed into one httpRequest using a minifier. They are left separate here for readability. There is a snippet at the bottom of this post showing what the code looks like with the minifier.

在code为asyncLoader.js如下:

The code for asyncLoader.js is the following:

/**
 * 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被完全加载脚本。

I added the option to run a script immediately, if you have scripts that don't rely on the page DOM being fully loaded.

缩小的要求实际上是这样的:

The minified requests actually look like:

<script type="text/javascript" src="/min/?b=javascript/lib&f=prototype/prototype.js,asyncLoader.js"></script>
<script type="text/javascript"> initPage = function(e){...}</script>
<script type="text/javascript">
    srcstr = "/min/?f=<?=implode(',', $js_files)?>";
    loadScriptAsync(srcstr, initPage);
 </script>

他们正在使用的插件来自: HTTP://$c$c.google。 COM / p /缩小/

感谢您的帮助!结果
-K

Thanks for the help!!
-K

推荐答案

您需要的是的onload 功能简单的队列即可。还请避免浏览器嗅探,因为它是不稳定的,而不是面向未来。完整的源$ C ​​$ C看到 [演示]

What you need is a simple queue of onload functions. Also please avoid browser sniffing as it is unstable and not future proof. For full source code see the [Demo]

var onload_queue = [];
var dom_loaded = false;

function loadScriptAsync(src, callback) {
  var script = document.createElement('script'); 
  script.type = "text/javascript";
  script.async = true;
  script.src = src;
  script.onload = script.onreadystatechange = function() {
    if (dom_loaded) 
      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);
}

function domLoaded() {
   dom_loaded = true;
   var len = onload_queue.length;
   for (var i = 0; i < len; i++) {
     onload_queue[i]();
   }
   onload_queue = null;
};

// Dean's dom:loaded code goes here
// do stuff
domLoaded();

测试使用

loadScriptAsync(
  "http://code.jquery.com/jquery-1.4.4.js", 
  function() {
      alert("script has been loaded");
   }
);

这篇关于加载JavaScript的异步,然后检查DOM执行回调之前加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆