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 相关文章推荐
Jsonp 跨域的原理以及Jquery的解决方案
May 18 Javascript
用js闭包的方法实现多点标注冒泡示例
May 29 Javascript
JavaScript通过元素索引号删除数组中对应元素的方法
Mar 18 Javascript
JavaScript使用replace函数替换字符串的方法
Apr 06 Javascript
限制文本框只能输入数字||只能是数字和小数点||只能是整数和浮点数
May 27 Javascript
浅谈JavaScript函数的四种存在形态
Jun 08 Javascript
Jquery Easyui进度条组件Progress使用详解(8)
Mar 26 Javascript
jQuery读取XML文件的方法示例
Feb 03 Javascript
Angular4 中常用的指令入门总结
Jun 12 Javascript
vue后台管理之动态加载路由的方法
Aug 13 Javascript
详解适配器在JavaScript中的体现
Sep 28 Javascript
Vue router配置与使用分析讲解
Dec 24 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
修改WordPress中文章编辑器的样式的方法详解
2015/12/15 PHP
Javascript公共脚本库系列(一): 弹出层脚本
2011/02/24 Javascript
dojo随手记 gird组件引用
2011/02/24 Javascript
ASP.NET jQuery 实例7 通过jQuery来获取DropDownList的Text/Value属性值
2012/02/03 Javascript
nodejs win7下安装方法
2012/05/24 NodeJs
解决window.opener=null;window.close(),只支持IE6不支持IE7,IE8的问题
2014/01/14 Javascript
JS实现可缩放、拖动、关闭和最小化的浮动窗口完整实例
2015/03/04 Javascript
JavaScript获取页面上被选中文字的方法技巧
2015/03/13 Javascript
JS实现可直接显示网页代码运行效果的HTML代码预览功能实例
2015/08/06 Javascript
JS实现的表格行鼠标点击高亮效果代码
2015/11/27 Javascript
Vue.js实战之组件之间的数据传递
2017/04/01 Javascript
聊聊JavaScript如何实现继承及特点
2017/04/07 Javascript
使用JavaScript进行表单校验功能
2017/08/01 Javascript
jquery中有哪些api jQuery主要API
2017/11/20 jQuery
Element-ui DatePicker显示周数的方法示例
2019/07/19 Javascript
使用element-ui的el-menu导航选中后刷新页面保持当前选中状态
2019/07/19 Javascript
JS使用正则表达式判断输入框失去焦点事件
2019/10/16 Javascript
vue 防止页面加载时看到花括号的解决操作
2020/11/09 Javascript
windows如何把已安装的nodejs高版本降级为低版本(图文教程)
2020/12/14 NodeJs
[37:23]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#2Secret VS EG第二局
2016/03/04 DOTA
[05:43]VG.R战队教练Mikasa专访:为目标从未停止战斗
2016/08/02 DOTA
Python 的 with 语句详解
2014/06/13 Python
Python实现的监测服务器硬盘使用率脚本分享
2014/11/07 Python
Python2与Python3的区别实例分析
2019/04/11 Python
python 中如何获取列表的索引
2019/07/02 Python
vue常用指令代码实例总结
2020/03/16 Python
GAP阿联酋官网:GAP UAE
2017/11/30 全球购物
阿玛尼美妆英国官网:Giorgio Armani Beauty英国
2019/03/28 全球购物
德国最大的网上足球商店:11teamsports
2019/09/11 全球购物
软件测试常见笔试题
2012/02/04 面试题
什么是lambda函数
2013/09/17 面试题
英语生日邀请函
2014/01/23 职场文书
报告会主持词
2014/04/02 职场文书
2016年“我们的节日·中秋节”活动总结
2016/04/05 职场文书
golang interface判断为空nil的实现代码
2021/04/24 Golang
python高温预警数据获取实例
2022/07/23 Python