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 相关文章推荐
JavaScript中判断函数是new还是()调用的区别说明
Apr 07 Javascript
javascript禁止访客复制网页内容的实现代码
Aug 05 Javascript
jqGrid表格应用之新增与删除数据附源码下载
Dec 02 Javascript
微信小程序 动态绑定事件并实现事件修改样式
Apr 13 Javascript
JS实现多张图片预览同步上传功能
Jun 23 Javascript
vue router-link传参以及参数的使用实例
Nov 10 Javascript
浅谈vue的props,data,computed变化对组件更新的影响
Jan 16 Javascript
结合Vue控制字符和字节的显示个数的示例
May 17 Javascript
AngularJS ui-router刷新子页面路由的方法
Jul 23 Javascript
详解javascript对数组和json数组的操作
Apr 15 Javascript
Vue中跨域及打包部署到nginx跨域设置方法
Aug 26 Javascript
微信小程序 简易计算器实现代码实例
Sep 02 Javascript
深入理解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
thinkphp中连接oracle时封装方法无法用的解决办法
2013/06/17 PHP
基于php中使用excel的简单介绍
2013/08/02 PHP
destoon实现底部添加你是第几位访问者的方法
2014/07/15 PHP
PHP常见数组函数用法小结
2016/03/21 PHP
PHP实现基于栈的后缀表达式求值功能
2017/11/10 PHP
PHP mongodb操作类定义与用法示例【适合mongodb2.x和mongodb3.x】
2018/06/16 PHP
javascript中的几个运算符
2007/06/29 Javascript
js常见表单应用技巧
2008/01/09 Javascript
jQuery中事件对象e的事件冒泡用法示例介绍
2014/04/25 Javascript
jQuery中:checkbox选择器用法实例
2015/01/03 Javascript
js中hash和ico的关联分析
2015/02/05 Javascript
以Python代码实例展示kNN算法的实际运用
2015/10/26 Javascript
详解JavaScript对象序列化
2016/01/19 Javascript
详解jQuery选择器
2016/12/21 Javascript
微信小程序 http请求的session管理
2017/06/07 Javascript
jQuery实现鼠标移入移出事件切换功能示例
2018/09/06 jQuery
基于JavaScript实现简单的轮播图
2021/03/03 Javascript
[04:02]2014DOTA2国际邀请赛 BBC每日综述中国战队将再度登顶
2014/07/21 DOTA
[11:42]2018DOTA2国际邀请赛寻真——OG卷土重来
2018/08/17 DOTA
Python中的pprint折腾记
2015/01/21 Python
Python中的MongoDB基本操作:连接、查询实例
2015/02/13 Python
python执行外部程序的常用方法小结
2015/03/21 Python
在Python的Bottle框架中使用微信API的示例
2015/04/23 Python
Python通过TensorFlow卷积神经网络实现猫狗识别
2019/03/14 Python
python安装virtualenv虚拟环境步骤图文详解
2019/09/18 Python
Python关于反射的实例代码分享
2020/02/20 Python
使用PyQt5实现图片查看器的示例代码
2020/04/21 Python
matplotlib图例legend语法及设置的方法
2020/07/28 Python
html5教程实现Photoshop渐变色效果
2013/12/04 HTML / CSS
ReVive利维肤美国官网:RéVive Skincare
2018/04/18 全球购物
模特大赛策划方案
2014/05/28 职场文书
2014年党员加强作风建设思想汇报
2014/09/15 职场文书
借款协议书
2014/09/16 职场文书
召开会议通知范文
2015/04/15 职场文书
大学生奶茶店创业计划书
2019/06/25 职场文书
MySQL的prepare使用以及遇到的bug
2022/05/11 MySQL