JavaScript文件同步与异步加载详解

作者:异步漫步时间:2026-10-22 07:30:14浏览:291

本文深入解析JavaScript文件的加载机制,对比同步加载与异步加载的优劣。通过Script Element动态创建和AJAX请求两种方式实现异步加载,并解决依赖文件的加载顺序问题,旨在优化页面性能与用户体验。

JavaScript文件加载概述

尽管当前存在Webpack、CommonJS、RequireJS等框架和工具对资源管理进行了优化,但掌握原生JavaScript的文件加载机制依然具有重要价值。本文将简要介绍几种实现JS文件同步与异步加载的方法。

同步加载机制与局限

同步加载机制

最基础的方式是在HTML文件中直接使用<script>标签引入JS文件,这是初学者最常接触到的加载模式。

为了演示加载效果,准备两个JS文件:

calc1.js


console.log('calc1 loading begin')

function add(...args) {
  return args.reduce((currentTotal, i) => currentTotal + i, 0);
}
console.log('calc1 loading end')

calc2.js


console.log('calc2 loading begin')

console.log(add(1,2,3))

console.log('calc2 loading end')

其中,calc2.js的执行依赖于calc1.js中定义的函数。

对应的HTML文件结构如下:


<body>

  <script src="calc1.js">
  </script>
  
  <script src="calc2.js">
  </script>
</body>

在这种同步加载模式下,浏览器会按顺序执行脚本。即calc1.js完全加载并执行完毕后,才会开始加载calc2.js。这种机制确保了calc2.js能够正确调用calc1.js中定义的add函数。在Chrome浏览器中的调试结果验证了这一点:

JavaScript文件加载概述

然而,同步加载存在明显的缺点。当涉及多个JS文件时,总加载时间会显著增加,并且由于浏览器在加载脚本时会阻塞HTML解析和用户界面响应,导致用户体验下降。

Script Element异步加载方案

通过Script Element实现异步加载

异步加载的主要优势在于能够并行加载多个JS文件,且不会阻塞用户界面的渲染,从而提升用户体验。其不足之处在于无法保证存在依赖关系的文件之间的加载顺序。

以下是使用Script Element进行异步加载的HTML代码示例:


<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script type="text/javascript">
    var script1 = document.createElement('script');
    script1.src='calc1.js';
    script1.type='text/javascript';

    var script2 = document.createElement('script');
    script2.src='calc2.js';
    script2.type='text/javascript';

    document.getElementsByTagName('head')[0].appendChild(script1).appendChild(script2);
  </script>
</head>

在Chrome浏览器中调试时,有时能够看到正确的输出结果:

JavaScript文件加载概述

但由于calc1.js未必先于calc2.js加载,calc2.js在执行时可能会因找不到add函数而报错。

JavaScript文件加载概述

因此,我们需要解决加载顺序问题,确保calc1.js优先加载。


<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script type="text/javascript">
    function loadScript(file, callbackFn) {
      var script = document.createElement('script');
      script.src= file;
      script.type='text/javascript';
      // 监听onload时间,当前js文件加载完成后,再加载下一个
      script.onload = callbackFn;
      document.getElementsByTagName('head')[0].appendChild(script)
    }
    
    loadScript('calc1.js', function () {
      loadScript('calc2.js');
    } );

  </script>
</head>

通过调整加载逻辑,即可始终获得正确的输出结果。

AJAX加载JS文件方案

通过AJAX加载JS文件


 <script>
    function loadScript(file, callbackFn) {
      var xhr = new XMLHttpRequest();
      xhr.open('get', file, true);
      // for IE
      if (xhr.onreadystatechange) {
        xhr.onreadystatechange = function () {
          console.log(xhr.readyState, xhr.status);
          if (xhr.readyState == 4) {
            if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
              insertScriptText(xhr.responseText);
              if (callbackFn) {
                callbackFn();
              }
            }
          }
        }
      } else {
        xhr.onload = function () {
          insertScriptText(xhr.responseText);
          if (callbackFn) {
            callbackFn();
          }
        }
      }
      xhr.send(null);
    }

    function insertScriptText(scriptText) {
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.text = scriptText;
      document.body.appendChild(script);
    }

    loadScript('calc1.js', function () {
      loadScript('calc2.js');
    });

  </script>

该方法同样能够正确输出结果。

JavaScript文件加载概述

加载方式总结与建议

总结

对于单一或少量的JS文件,建议在HTML body标签末尾插入script标签,采用同步方式加载。值得注意的是,Webpack等构建工具通常将多个JS文件合并为一个,并在body中插入script引用,这也是一种同步加载的变体。

对于包含多个JS文件的场景,建议采用异步加载策略,以避免阻塞界面渲染并缩短整体加载时间。本文介绍了Script Element动态创建和AJAX请求两种异步加载方式,并针对存在依赖关系的文件加载顺序提供了实例解决方案。更多细节请参考:https://github.com/JackieGe/Js-Learn/tree/master/ch1-async-loading

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章