JavaScript-异步加载

同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续的文件加载(如图像)、渲染、代码执行。

 js 之所以要同步执行,是因为 js 中可能有输出 document 内容、修改dom、重定向等行为,所以默认同步执行才是安全的。

js默认是同步模式,所以我们一般写在</body>之前,因为我们一旦遇到这样的js代码,就得停下来加载。

想想我们打开一个页面时,什么都没有,你还想用它吗?肯定是最基础的html,css得加载出来吧。

js异步加载的缺点:有一些加载工具方法,没必要阻塞文档,过多的js加载会影响页面效率,一旦网速不好,那么整个网站都会等待js加载而不进行渲染工作。


js实现异步加载有三种方法:

1:defer

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

    <script  type='text/javascript' src='jq.js' defer='defer'></script>

那么这个时候遇到了,不会停下来加载js文件,而是重新再启动一个线程来加载这个文件。

执行时刻是文档被解析完时。


2.async异步加载,加载完成时,就执行。async只能加载外部脚本,不能把js写到script标签里面。

IE9以上兼容。

    <script  type='text/javascript' src='jq.js' async='async'></script>
    <script  type='text/javascript'  async='async'>
       var a=3;
    </script>

第二个是错误的,不能在里面写代码。其他和第一个一样。

3.

onload事件。当对象加载完成时就执行。

但是IE上的script标签上没有这个,它提供了一个状态码readyState 它里面存着一些状态。

script.readyState 一开始存'loading' ,加载完成是'complete' 或者'loaded'.

IE还提供了一个事件 onreadystatechange,但readystate发现改变时,那么就触发。

var script=document.createElement('script');
script.style='text/javascript';
script.src='jq.js';
scrip.onreadystatechange =function() {
    if (script.readyState=='complete'||script.readyState='loaded') {
             //执行
     }
 }

我们封装一个函数,当我们需要异步加载某个js的文件时,然后加载完成时执行某个函数callBack(加载文件里面的函数)

         function loadScript(url,callBack) {
             var script=document.createElement('script');
             script.style='text/javascript';
             if (script.readyState) {
                 script.onreadystatechange=function() {
                     if (script.readyState=='complete'||script.readyState=='loaded') {
                         callBack();
                     }
                 }
             }
             else {
                 script.onload =function() {
                     callBack();
                 }
             }
             script.src=url;//我们先绑定事件,再加载文件,因为如果先加载,万一文件很小,加载完了,下面代码还没执行,readyState就变了,就尴尬了。
             document.head.appendChild(script);
         }

这样,我们如果调用的时候就得这样写。

    loadScript('jp.js',function() {
        //需要执行的函数
    });

也可以传字符串进出,那么用eval来解决。

为什么了?很明显,如果我们直接将函数引用写上去,文件都没有加载出来,函数引用哪里来的?我们套一层函数,预处理的时候,就不会管函数里面的代码是什么内容。



猜你喜欢

转载自blog.csdn.net/wust_cyl/article/details/80138877