JavaScript动态加载JS文件并执行回调

作者:半夏

时间:2026-10-30

浏览:120

本文介绍如何在JavaScript中动态加载外部JS文件并检测加载完成状态。通过创建script元素,利用IE的onreadystatechange和非IE浏览器的onload事件,实现了串行和并行两种加载模式。串行加载按顺序执行,并行加载同时发起请求,两者均支持在全部加载完成后执行回调函数,兼容主流浏览器。

文章目录

JavaScript动态加载JS文件并执行回调

在JavaScript开发中,动态加载其他JS文件是一个常见需求。然而,许多开发者并不清楚如何准确判断外部JS文件是否加载完成。如果在文件未加载完毕时就调用其中的函数,操作将会失败。本文将详细讲解如何在JS中动态加载其他JS文件,并在加载完成后执行指定的回调函数。

我们可以通过动态创建<script>元素,并修改其src属性来加载脚本。关键在于如何判断脚本文件加载完成,因为某些函数必须在脚本生效后才能执行。通过查阅相关资料发现,在IE浏览器中,可以利用<script>元素的onreadystatechange事件监控加载状态变化,并通过检查readyState属性值为loaded或complete来判断加载是否完成。而在非IE浏览器中,可以直接使用onload事件来判断脚本是否加载完成。

一个基础的实现过程大致如下所示:


//IE下:
var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.onreadystatechange = function() {
  if(this.readyState == "loaded" || this.readyState == "complete"){
    alert("加载成功啦!");
  }
}
script.setAttribute("src",scripts[i]);

//Opera、FF、Chrome等:
var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.onload = function() {
  alert("加载成功啦!");
}
script.setAttribute("src",scripts[i]); 

串行与并行加载实现原理

其原理十分直观。基于上述两种机制,我们对代码进行了优化,将其封装为两个独立的函数,分别用于实现脚本的串行加载和并行加载。

当传入一个包含多个JS文件路径的数组时,串行加载函数会从第一个脚本开始加载,每成功加载一个脚本,便立即开始加载下一个脚本,直到所有脚本加载完成后,再执行回调函数。而并行加载则是在初始阶段就同时加载所有脚本文件,即它们从同一时间点开始加载,待所有脚本全部加载完成后,再执行回调函数。

经过实际测试,这两种加载函数均能兼容目前所有主流浏览器。


/** 
 * 串联加载指定的脚本
 * 串联加载[异步]逐个加载,每个加载完成后加载下一个
 * 全部加载完成后执行回调
 * @param array|string 指定的脚本们
 * @param function 成功后回调的函数
 * @return array 所有生成的脚本元素对象数组
 */

function seriesLoadScripts(scripts,callback) {
  if(typeof(scripts) != "object") var scripts = [scripts];
  var HEAD = document.getElementsByTagName("head").item(0) || document.documentElement;
  var s = new Array(), last = scripts.length - 1, recursiveLoad = function(i) { //递归
    s[i] = document.createElement("script");
    s[i].setAttribute("type","text/javascript");
    s[i].onload = s[i].onreadystatechange = function() { //Attach handlers for all browsers
      if(!/*@cc_on!@*/0 || this.readyState == "loaded" || this.readyState == "complete") {
        this.onload = this.onreadystatechange = null; this.parentNode.removeChild(this); 
        if(i != last) recursiveLoad(i + 1); else if(typeof(callback) == "function") callback();
      }
    }
    s[i].setAttribute("src",scripts[i]);
    HEAD.appendChild(s[i]);
  };
  recursiveLoad(0);
}
 

/**
 * 并联加载指定的脚本
 * 并联加载[同步]同时加载,不管上个是否加载完成,直接加载全部
 * 全部加载完成后执行回调
 * @param array|string 指定的脚本们
 * @param function 成功后回调的函数
 * @return array 所有生成的脚本元素对象数组
 */

function parallelLoadScripts(scripts,callback) {
  if(typeof(scripts) != "object") var scripts = [scripts];
  var HEAD = document.getElementsByTagName("head").item(0) || document.documentElement, s = new Array(), loaded = 0;
  for(var i=0; i<scripts.length; i++) {
    s[i] = document.createElement("script");
    s[i].setAttribute("type","text/javascript");
    s[i].onload = s[i].onreadystatechange = function() { //Attach handlers for all browsers
      if(!/*@cc_on!@*/0 || this.readyState == "loaded" || this.readyState == "complete") {
        loaded++;
        this.onload = this.onreadystatechange = null; this.parentNode.removeChild(this); 
        if(loaded == scripts.length && typeof(callback) == "function") callback();
      }
    };
    s[i].setAttribute("src",scripts[i]);
    HEAD.appendChild(s[i]);
  }
}

在此实现中,<script>标签被动态插入到页面的<head>标签内部,并且在加载完成后,该标签元素会被自动移除。此外,代码中使用了一种称为条件编译的技巧作为表达式(!/*@cc_on!@*/0)来判断是否为非IE浏览器。条件编译并非本文重点,有兴趣的读者可自行查阅相关资料深入学习。

函数使用示例

以下是这两个函数的具体使用方法:我们声明了一个数组变量,其中包含了两个远程JS文件的地址(需要注意的是,<script>标签调用脚本是支持跨域的):


var scripts = [ 
  "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js",
  "http://wellstyled.com/files/jquery.debug/jquery.debug.js"
];

//这两个文件分别是 jQuery 1.4.的库文件和 jQuery Debug 插件
//然后你可以使用下面的方法调用并在成功后执行回调了。

seriesLoadScripts(scripts,function(){ 

  /*
  debug = new $.debug({ 
    posTo : { x:'right', y:'bottom' },
    width: '480px',
    height: '50%',
    itemDivider : '<hr>',
    listDOM : 'all'
  }); 

  */
  alert('脚本加载完成啦');
});

这里演示的是使用串联加载函数,当然你也可以根据实际需求选择并联加载函数。建议当后续脚本依赖于前一个脚本时,使用串联加载;否则,推荐使用并联加载,因为从原理上讲,并联加载的速度略快于串联加载。

以上就是本文的全部内容,希望这对大家的学习有所帮助,也欢迎大家多多支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章