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 相关文章推荐
extjs 为某个事件设置拦截器
Jan 15 Javascript
jquery form表单提交插件asp.net后台中文解码
Jun 12 Javascript
解决自定义$(id)的方法与jquery选择器$冲突的问题
Jun 14 Javascript
JavaScript中发布/订阅模式的简单实例
Nov 05 Javascript
JavaScript使用setInterval()函数实现简单轮询操作的方法
Feb 02 Javascript
Javascript实现检测客户端类型代码封包
Dec 03 Javascript
javascript鼠标滑过显示二级菜单特效
Nov 18 Javascript
微信小程序 picker-view 组件详解及简单实例
Jan 10 Javascript
JavaScript设计模式之观察者模式实例详解
Jan 16 Javascript
JS中min函数实例讲解
Feb 18 Javascript
ES6入门教程之let、const的使用方法
Apr 13 Javascript
详解Vue的七种传值方式
Feb 08 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错误抑制符(@)导致引用传参失败Bug的分析
2011/05/02 PHP
php数组合并array_merge()函数使用注意事项
2014/06/19 PHP
php中strstr、strrchr、substr、stristr四个函数的区别总结
2014/09/22 PHP
动态样式类封装JS代码
2009/09/02 Javascript
js 判断脚本加载完毕的代码
2011/07/13 Javascript
Jquery弹出层插件ThickBox的使用方法
2014/12/09 Javascript
javascript多物体运动实现方法分析
2016/01/08 Javascript
JS中多种方式创建对象详解
2016/03/22 Javascript
jQuery+CSS实现一个侧滑导航菜单代码
2016/05/09 Javascript
AngularJs directive详解及示例代码
2016/09/01 Javascript
Node.js连接MongoDB数据库产生的问题
2017/02/08 Javascript
VueJS组件之间通过props交互及验证的方式
2017/09/04 Javascript
使用jQuery实现两个div中按钮互换位置的实例代码
2017/09/21 jQuery
Vue 全家桶实现移动端酷狗音乐功能
2018/11/16 Javascript
如何使用puppet替换文件中的string
2018/12/06 Javascript
JS函数进阶之继承用法实例分析
2020/01/15 Javascript
[57:31]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第一场 2月1日
2021/03/11 DOTA
python 快速排序代码
2009/11/23 Python
布同自制Python函数帮助查询小工具
2011/03/13 Python
结合Python的SimpleHTTPServer源码来解析socket通信
2016/06/27 Python
由浅入深讲解python中的yield与generator
2017/04/05 Python
python学习教程之使用py2exe打包
2017/09/24 Python
详谈Python3 操作系统与路径 模块(os / os.path / pathlib)
2018/04/26 Python
Python 如何优雅的将数字转化为时间格式的方法
2019/09/26 Python
flask利用flask-wtf验证上传的文件的方法
2020/01/17 Python
Python多线程threading创建及使用方法解析
2020/06/17 Python
Myprotein加拿大官网:欧洲第一的运动营养品牌
2018/01/06 全球购物
中科创达面试题
2016/12/28 面试题
Python里面search()和match()的区别
2016/09/21 面试题
《雷鸣电闪波尔卡》教学反思
2014/02/23 职场文书
大学生怎样写好自荐信
2014/02/25 职场文书
文体活动实施方案
2014/03/27 职场文书
怎样写辞职信
2015/02/27 职场文书
网吧管理制度范本
2015/08/05 职场文书
Python实现GIF动图以及视频卡通化详解
2021/12/06 Python
vue 把二维或多维数组转一维数组
2022/04/24 Vue.js