JS的异步加载

2019-08-19  本文已影响0人  zooeydotmango

为什么要异步加载

浏览器下载除JS外的资源时,会并行下载,以提高性能。但下载JS脚本时,会禁止并行下载(称为脚本阻塞Scripts Block Downloads)。浏览器遇到JS时,必须等JS下载,解析,执行完后,才能继续并行下载下一个资源。原因是JS可能会改变页面或改变JS间的依赖关系,例如A.js中用document.write改变页面,B.js依赖于A.js。因此要严格保证顺序,不能并行下载。

因此不推荐将JS放到<head>标签里,浏览器遇到<script>标签会下载,解析,执行完脚本后,才继续处理剩余的页面部分。

为了避免白屏,通常的建议是将JS放到<body>标签底下,可以有最佳的用户体验,你可以点击例子页面试一下。如果你放到了<body>标签的上部,因为脚本阻塞,可能会影响用户体验。例子中位于<body>上部的JS耗时2s,因此位于JS下面的两张img图片,会等2s后才开始加载。

将JS放在<body>底下的建议没有错,几乎成了前端的普世规则。但对于追求极致用户体验的站点,或大型网站来说,这还不够。

异步加载的方法

Dynamic Script Element动态脚本元素

该技术不但简单,而且通用,且可以跨域,应该成为你的首选

var script = document.createElement('script');  //创建script标签
script.type = "text/javascript";
script.src = "A.js";
document.getElementsByTagName('head')[0].appendChild(script);   //塞进页面

当JS下载完毕后,就会立即执行。如果多个JS间有依赖关系,一下载完马上执行可能会出现error。因此通常来说你应该将有依赖关系的JS合并成一个文件,虽然合并后JS文件会变大,但由于是异步下载,你几乎不会有什么损失。
如果实在不方便将有依赖关系的文件合并。你需要自己指定先后顺序,通过监听load事件(IE是onreadystatechange)来确保依次加载脚本:

function loadScript(url, callback){
    var script = document.createElement ("script")
    script.type = "text/javascript";

    if (script.readyState){ //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" || script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    } else { //Others
        script.onload = function(){
            callback();
        };
    }
    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

//严格确保A->B->C,依次下载脚本文件
loadScript("A-delay.js", function(){
    loadScript("B-delay.js", function(){
        loadScript("C-delay.js", function(){
            console.log("All files are loaded!");
        });
    });
});

Script async

HTML5里为script标签里新增了async属性,用于异步加载脚本

<script type="text/javascript" src="alert.js" async="async"></script>

1.async属性是HTML5新增属性,需要Chrome、FireFox、IE9+浏览器支持
2.async属性规定一旦脚本可用,则会异步执行
3.async属性仅适用于外部脚本
4.此方法不能保证脚本按顺序执行

Script defer

script标签里可以设置defer,表示延迟加载脚本:

<script type="text/javascript" src="alert.js" defer="defer"></script>

1.defer属性规定是否对脚本执行进行延迟,直到页面加载为止
2.如果脚本不会改变文档的内容,可将defer属性加入到<script>标签中,以便加快处理文档的速度
3.兼容所有浏览器
4.此方法可以确保所有设置了defer属性的脚本按顺序执行

更多

更多方法见
异步加载JS脚本

上一篇 下一篇

猜你喜欢

热点阅读