JavaScript文件的同步和异步加载的实现代码


Posted in Javascript onAugust 19, 2017

对于JS文件的引用,尽管当前有不少框架和工具(比如webpack,commonjs,requiresjs等)都做了很好的处理。但是抛开这些框架,了解原生的加载方式还是不无裨益。本文简述一些js文件的同步和异步加载方式。

同步加载

可在html文件里以<script>标签插入,这是初学时最基本的方式。

准备两个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里的add函数。在Chrome里的调试结果如下:

JavaScript文件的同步和异步加载的实现代码

但同步加载的缺点也明显,如果有多个文件的时候,全部加载时间会很长,而且阻塞用户界面响应。

通过Script Element异步加载

异步加载的优点是,能够同时加载多个js文件,而且由于是异步,不会阻塞用户界面,用户体验好。当然缺点是,不能保证有依赖关系的文件的加载顺序。

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文件的同步和异步加载的实现代码

但有时候由于clac1.js没有被先加载,calc2.js执行时会报错。

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文件
 

<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

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

Javascript 相关文章推荐
ie focus bug 解决方法
Sep 03 Javascript
ASP.NET jQuery 实例10 动态修改hyperlink的URL值
Feb 03 Javascript
JavaScript在XHTML中的用法详解
Apr 11 Javascript
js切换光标示例代码
Oct 10 Javascript
Query常用DIV操作获取和设置长度宽度的实现方法
Sep 19 Javascript
KnockoutJS 3.X API 第四章之数据控制流if绑定和ifnot绑定
Oct 10 Javascript
详解jQuery中的DOM操作
Dec 23 Javascript
js中的DOM模拟购物车功能
Mar 22 Javascript
webpack独立打包和缓存处理详解
Apr 03 Javascript
前端Vue项目详解--初始化及导航栏
Jun 24 Javascript
js简单粗暴的发布订阅示例代码
Jan 23 Javascript
vue实现登陆页面开发实践
May 30 Vue.js
深入理解ES6学习笔记之块级作用域绑定
Aug 19 #Javascript
深入理解ES6的迭代器与生成器
Aug 19 #Javascript
Mui使用jquery并且使用点击跳转新窗口的实例
Aug 19 #jQuery
Vue自定义事件(详解)
Aug 19 #Javascript
Vue内容分发slot(全面解析)
Aug 19 #Javascript
简单的网页广告特效实例
Aug 19 #Javascript
JavaScript 完成注册页面表单校验的实例
Aug 19 #Javascript
You might like
php中长文章分页显示实现代码
2012/09/29 PHP
Symfony2框架学习笔记之表单用法详解
2016/03/18 PHP
PHP空值检测函数与方法汇总
2017/11/19 PHP
彪哥1.1(智能表格)提供下载
2006/09/07 Javascript
用javascript实现的仿Flash广告图片轮换效果
2007/04/24 Javascript
Javascript 实现TreeView CheckBox全选效果
2010/01/11 Javascript
js 强制弹出窗口代码研究-又一款代码
2010/03/20 Javascript
Javascript实现滑块滑动改变值的实现代码
2013/04/12 Javascript
Node.js中使用Buffer编码、解码二进制数据详解
2014/08/16 Javascript
JavaScript之数组(Array)详解
2015/04/01 Javascript
JavaScript获得表单target属性的方法
2015/04/02 Javascript
基于jQuery实现自动轮播旋转木马特效
2015/11/02 Javascript
JS实现兼容各种浏览器的获取选择文本的方法【测试可用】
2016/06/21 Javascript
AngularJS extend用法详解及实例代码
2016/11/15 Javascript
如何解决hover在ie6中的兼容性问题
2016/12/15 Javascript
使用ES6语法重构React代码详解
2017/05/09 Javascript
Three.js中网格对象MESH的属性与方法详解
2017/09/27 Javascript
js实现上传并压缩图片效果
2018/01/10 Javascript
详解Angular中通过$location获取地址栏的参数
2018/08/02 Javascript
JS实现随机抽取三人
2019/11/06 Javascript
jQuery带控制按钮轮播图插件
2020/07/31 jQuery
python Crypto模块的安装与使用方法
2017/12/21 Python
python广度优先搜索得到两点间最短路径
2019/01/17 Python
基于Python安装pyecharts所遇的问题及解决方法
2019/08/12 Python
记一次pyinstaller打包pygame项目为exe的过程(带图片)
2020/03/02 Python
Python新手学习raise用法
2020/06/03 Python
NFL墨西哥官方商店:Tienda NFL
2017/11/28 全球购物
交通专业个人自荐信格式
2013/09/23 职场文书
实习老师个人总结的自我评价
2013/09/28 职场文书
房产买卖委托公证书
2014/04/04 职场文书
爱心捐书活动总结
2014/07/05 职场文书
武夷山导游词
2015/02/03 职场文书
创业计划书之餐饮
2019/09/02 职场文书
pytorch损失反向传播后梯度为none的问题
2021/05/12 Python
oracle索引总结
2021/09/25 Oracle
一文搞懂PHP中的抽象类和接口
2022/05/25 PHP