JavaScript动态加载JS文件并执行回调
本文介绍如何在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('脚本加载完成啦');
});
这里演示的是使用串联加载函数,当然你也可以根据实际需求选择并联加载函数。建议当后续脚本依赖于前一个脚本时,使用串联加载;否则,推荐使用并联加载,因为从原理上讲,并联加载的速度略快于串联加载。
以上就是本文的全部内容,希望这对大家的学习有所帮助,也欢迎大家多多支持本站。
JavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13
