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 拖动表格行实现代码
May 05 Javascript
对javascript的一点点认识总结《javascript高级程序设计》读书笔记
Nov 30 Javascript
js菜单点击显示或隐藏效果的简单实例
Jan 13 Javascript
js实现飞入星星特效代码
Oct 17 Javascript
详细解读JavaScript的跨浏览器事件处理
Aug 12 Javascript
javascript创建含数字字母的随机字符串方法总结
Aug 01 Javascript
如何提高javascript加载速度
Dec 26 Javascript
基于JavaScript实现屏幕滚动效果
Jan 18 Javascript
5 种JavaScript编码规范
Jan 30 Javascript
JS二级菜单不同实现方法分析【4种方法】
Dec 21 Javascript
Vue 封装防刷新考试倒计时组件的实现
Jun 05 Javascript
浅析JavaScript中的事件委托机制跟深浅拷贝
Jan 20 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
php park、unpark、ord 函数使用方法(二进制流接口应用实例)
2010/10/19 PHP
php压缩多个CSS为一个css的代码并缓存
2011/04/21 PHP
php skymvc 一款轻量、简单的php
2011/06/28 PHP
让Nginx支持ThinkPHP的URL重写和PATHINFO的方法分享
2011/08/08 PHP
PHP原生函数一定好吗?
2014/12/08 PHP
php原生导出excel文件的两种方法(推荐)
2016/11/19 PHP
PHP AjaxForm提交图片上传并显示图片源码
2016/11/29 PHP
js树形控件脚本代码
2008/07/24 Javascript
juqery 学习之三 选择器 子元素与表单
2010/11/25 Javascript
纯文字版返回顶端的js代码
2013/08/01 Javascript
js(JavaScript)实现TAB标签切换效果的简单实例
2014/02/26 Javascript
jQuery.holdReady()使用方法
2014/05/20 Javascript
浅析$(function) ready和onload 的区别
2016/09/03 Javascript
Vue form 表单提交+ajax异步请求+分页效果
2017/04/22 Javascript
详解vue.js的devtools安装
2017/05/26 Javascript
vue2 自定义动态组件所遇到的问题
2017/06/08 Javascript
js脚本编写简单刷票投票系统
2017/06/27 Javascript
JS实现unicode和UTF-8之间的互相转换互转
2017/07/05 Javascript
利用纯JS实现像素逐渐显示的方法示例
2017/08/14 Javascript
jQuery pjax 应用简单示例
2018/09/20 jQuery
微信小程序城市选择及搜索功能的方法
2019/03/22 Javascript
微信小程序如何获取群聊的openGid以及名称详解
2019/07/17 Javascript
Python实现PS滤镜的旋转模糊功能示例
2018/01/20 Python
对Python subprocess.Popen子进程管道阻塞详解
2018/10/29 Python
美国礼品卡商城: Gift Card Mall
2017/08/25 全球购物
会计专业毕业生自荐信范文
2013/12/20 职场文书
给民警的表扬信
2014/01/08 职场文书
大学生表扬信范文
2014/01/09 职场文书
中层竞聘演讲稿
2014/01/09 职场文书
小学数学课题方案
2014/06/15 职场文书
大学生创业计划书
2014/08/14 职场文书
2015年预算员工作总结
2015/05/14 职场文书
运动会闭幕式致辞
2015/07/29 职场文书
小学班主任教育随笔
2015/08/15 职场文书
HTML5 语义化标签(移动端必备)
2021/08/23 HTML / CSS
Linux安装Docker详细教程
2022/07/07 Servers