异步加载JS

  1. js加载的缺点:加载工具方法没必要阻塞文档,过得js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作。
  2. 有些工具方法需要按需加载,用到再加载,不用不加载。

 

 

 

异步加载JS

JavaScript异步加载的三种方案:

1.defer异步加载,但要等到dom文档全部解析完才会被执行。只有IE能用,也可以将代码写到内部

2.async异步加载,加载完就被执行,async只能加载外部脚本不能把js写在script标签里

1.2执行时也不阻塞页面

3.创建script,插入到DOM中,加载完毕之后callBack

1.defer

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>abraham</title>
    </head>
    <body>
        <script type="text/javascript" defer="defer">
            //异步加载的JavaScript
	     //不会阻断HTML和CSS的下载,一起并行下载
        </script>
    </body>
</html>

2.async

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>abraham</title>
    </head>
    <body>
        <script type="text/javascript" async="async" src="xxx.js">
            
        </script>
    </body>
</html>

3.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>abraham</title>
    </head>
    <body>
        <script type="text/javascript">
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "xxx.js";
        </script>
    </body>
</html>

现在只会去下载,不会执行,当你在添加上document.head.appendChild(script);的时候才会去执行。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>abraham</title>
    </head>
    <body>
        <script type="text/javascript">
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "xxx.js";
            document.head.appendChild(script);
        </script>
    </body>
</html>

DOM初探(33)——异步加载JS

我如果把document.head.appendChild(script);删除时,js.js文件现在已经下载了,但是没有js.js里面的内容并没有被执行!!

DOM初探(33)——异步加载JS

现在我执行这个test();能执行吗?

DOM初探(33)——异步加载JS

不行吧!也不是真的不行

 

DOM初探(33)——异步加载JS

我让他在一秒之后执行这个函数,可以被执行。DOM初探(33)——异步加载JS

那为什么一秒钟之后可以被执行,当前执行不了吧?是不是当前还没有下载完!

程序执行以微妙计的。

所以现在有没有一个东西能够提示咱们,js文件下载完了,然后才去调用他的方法。

DOM初探(33)——异步加载JS

这个就能确保下载完成之后再去执行test();

onload兼容:safariChromeFirefoxOpera都兼容

IEscript.reanyState(状态码),他会动态的去改变里面的东西,比如一开始script.reanyState=”loading”,当下载完成之后,会把loading改成loaded或者complete

DOM初探(33)——异步加载JS

 

咱们把他们封装成一个函数:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>abraham</title>
    </head>
    <body>
        <script type="text/javascript">
            function loadScript(url,callback){
                var script = document.createElement("script");
                script.type = "text/javascript";
                script.src = url;
                if(script.readyState){
                    script.onreadystatechange = function(){
                        if(script.readyState == "complete" || script.readyState == "loaded"){
                            callback();
                        }
                    }
                }else{
                    script.onload = function(){
                        callback();
                    }
                }
                document.head.appendChild(script);
            }
        </script>
    </body>
</html>

现在有一个问题:onreadystatechange监听的是readyState的变化,readyState一变,他就触发这个东西,你说有没有这种情况,我的电脑在服务器旁边插了一根10m宽的光线,比本机存储还要快,script.src = url;的时候,瞬间就把资源下载完了,下载完成之后,script.readyState瞬间就便到了最终的状态了,那下面再绑定onreadystatechange还有意义吗?人家瞬间就到了终止的状态了,就不会再改变了。
改:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>abraham</title>
    </head>
    <body>
        <script type="text/javascript">
            function loadScript(url,callback){
                var script = document.createElement("script");
                script.type = "text/javascript";
                if(script.readyState){
                    script.onreadystatechange = function(){
                        if(script.readyState == "complete" || script.readyState == "loaded"){
                            callback();
                        }
                    }
                }else{
                    script.onload = function(){
                        callback();
                    }
                }
                script.src = url;
                document.head.appendChild(script);
            }
        </script>
    </body>
</html>

我先执行这个绑定事件,然后再加载这个文件。

但是:

<html>
    <head>
        <meta charset="utf-8">
        <title>abraham</title>
    </head>
    <body>
        <script type="text/javascript">
            function loadScript(url,callback){
                var script = document.createElement("script");
                script.type = "text/javascript";
                if(script.readyState){
                    script.onreadystatechange = function(){
                        if(script.readyState == "complete" || script.readyState == "loaded"){
                            callback();
                        }
                    }
                }else{
                    script.onload = function(){
                        callback();
                    }
                }
                script.src = url;
                document.head.appendChild(script);
            }
            loadScript("js.js",test);
        </script>
    </body>
</html>

DOM初探(33)——异步加载JS

怎么回事?

执行顺序是先解析function loadScript(url,callback){},不会看里面是什么,然后再执行loadScript("js.js",test);去导致function的执行,所以你先塞进去了一个test,他都不知道是什么吧!

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>abraham</title>
    </head>
    <body>
        <script type="text/javascript">
            function loadScript(url,callback){
                var script = document.createElement("script");
                script.type = "text/javascript";
                if(script.readyState){
                    script.onreadystatechange = function(){
                        if(script.readyState == "complete" || script.readyState == "loaded"){
                            callback();
                        }
                    }
                }else{
                    script.onload = function(){
                        callback();
                    }
                }
                script.src = url;
                document.head.appendChild(script);
            }
            loadScript("js.js",function(){
                test();
            });
        </script>
    </body>
</html>

这叫做函数的引用,我传一个匿名函数进去,函数里面的函数体叫做test()

DOM初探(33)——异步加载JS

函数引用在读的时候不会读里面的代码,在执行的时候才会去读。

相关文章: