JS异步加载方案

2,570 阅读2分钟

我们知道渲染引擎遇到 script 标签会停下来,等加载并执行完该脚本,才继续向下渲染,这种传统js加载方式存在着明显的不足。当过多的js加载时,会严重影响页面渲染效率,一旦网速不好,那么整个网站将会等着,一直等待js加载执行,而不进行后续的渲染工作了。 有的时候在加载工具方法时,我们希望加载的同时不阻塞页面的渲染;有的时候有些工具方法按需加载,用到时再加载;这是就得用到异步加载了

JavaScript异步加载的三种方式

1. defer异步加载(IE可用)

<!--  1  -->
<script defer = "defer" src = "./index.js"></script>
<!--  2  -->
<script defer = "defer">
  //code
</script>

defer:遇到就去加载,但是要等DOM文档全部解析完才会被执行

2. async异步加载

<script async = "async" src = "./index.js"></script>

async:遇到就去加载,加载完就去执行,不考虑DOM是否解析完毕! async只能异步加载外部js,不能将js代码写在script标签内,让async去异步加载里面的js代码。

可同时使用async和defer,这样IE 4以上和其他浏览器都支持异步加载

<script  src = "./js/tools.js"  async  defer></script>

3. 手动封装,按需加载

手动封装一个方法,在需要的地方调用

// 手动封装异步加载js的方法
function asyncLoadScript(url, callback) {
  var script = document.createElement('script');
  script.type = 'text/javascript';
  if (script.readyState) {//readyState是IE中的状态码
    script.onreadystatechange = function () {
      //绑定监听状态码的事件,IE状态码变成complete或者loaded,表示该元素加载完
      if (script.readyState == "complete" || script.readyState == "loaded") {
        callback();//回调函数,当script加载完后调用
      }
    }
  } else {
    //非IE 用onload事件,表示当script加载完时
    script.onload = function () {
      callback();//回调函数,当script加载完后调用
    }
  }
  script.src = url;//放在这,是为了避免IE立即加载完,立即加载完就不再触发onreadystatechange
  document.head.appendChild(script);//加载到页面中去
}
//执行
asyncLoadScript('./js/tools.js', function () {
  //code
  console.log('按照加载完了:' + url + '文件')
});