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 相关文章推荐
二级域名转向类
Nov 09 Javascript
硬盘浏览程序,保存成网页格式便可使用
Dec 03 Javascript
jQuery Ajax 全解析
Feb 08 Javascript
jquery ui dialog里调用datepicker的问题
Aug 06 Javascript
Mootools 1.2教程 输入过滤第二部分(字符串)
Sep 15 Javascript
javascript parseInt 大改造
Sep 27 Javascript
关于jQuery的inArray 方法介绍
Oct 08 Javascript
jquery中attr和prop的区别分析
Mar 16 Javascript
通过JS获取Request.QueryString()参数的值实现方法
Sep 27 Javascript
jQuery 实现鼠标画框并对框内数据选中的实例代码
Aug 29 jQuery
详解基于vue的服务端渲染框架NUXT
Jun 20 Javascript
Jquery Fade用法详解
Nov 06 jQuery
深入理解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
模仿OSO的论坛(五)
2006/10/09 PHP
PHP 获取文件路径(灵活应用__FILE__)
2013/02/15 PHP
PHP 获取远程文件大小的3种解决方法
2013/07/11 PHP
php实现过滤字符串中的中文和数字实例
2015/07/29 PHP
thinkPHP+LayUI 流加载实现功能
2019/09/27 PHP
High Performance JavaScript(高性能JavaScript)读书笔记分析
2011/05/05 Javascript
使用PHP+JQuery+Ajax分页的实现
2013/04/23 Javascript
纯css实现窗户玻璃雨滴逼真效果
2015/08/23 Javascript
通过Jquery.cookie.js实现展示浏览网页的历史记录超管用
2015/10/23 Javascript
深入理解$.each和$(selector).each
2016/05/15 Javascript
jQuery基于Ajax方式提交表单功能示例
2017/02/10 Javascript
Vue.js:使用Vue-Router 2实现路由功能介绍
2017/02/22 Javascript
vue2路由方式--嵌套路由实现方法分析
2020/03/06 Javascript
Python 3实战爬虫之爬取京东图书的图片详解
2017/10/09 Python
深入理解Python中的 __new__ 和 __init__及区别介绍
2018/09/17 Python
python 实现查找文件并输出满足某一条件的数据项方法
2019/06/12 Python
基于Python的Post请求数据爬取的方法详解
2019/06/14 Python
Python正则表达式匹配数字和小数的方法
2019/07/03 Python
Python3+PyInstall+Sciter解决报错缺少dll、html等文件问题
2019/07/15 Python
python 修改本地网络配置的方法
2019/08/14 Python
PYQT5开启多个线程和窗口,多线程与多窗口的交互实例
2019/12/13 Python
深入了解Python enumerate和zip
2020/07/16 Python
Python 串口通信的实现
2020/09/29 Python
CSS3打造百度贴吧的3D翻牌效果示例
2017/01/04 HTML / CSS
HTML5注册页面示例代码
2014/03/27 HTML / CSS
【HTML5】3D模型--百行代码实现旋转立体魔方实例
2016/12/16 HTML / CSS
北欧最好的童装网上商店:Babyshop
2019/09/15 全球购物
汉语专业应届生求职信
2013/10/01 职场文书
《长城》教学反思
2014/02/14 职场文书
项目投资意向书
2014/04/01 职场文书
知识改变命运演讲稿
2014/05/21 职场文书
《风筝》教学反思
2016/02/23 职场文书
Django开发RESTful API实现增删改查(入门级)
2021/05/10 Python
MySQL系列之开篇 MySQL关系型数据库基础概念
2021/07/02 MySQL
彩虹社八名人气艺人全新周边限时推出,性转女装男装一次拥有!
2022/04/01 日漫
vue递归实现树形组件
2022/07/15 Vue.js