我有以下javascript列表,此列表中的每个项目都有一个脚本文件url和一个回调函数,我想要做的是迭代这个列表,加载每个脚本,然后执行回调函数,并且 NOT 移动到下一个项目,除非当前回调已完成执行..
var data = {
scripts: [
{
file : 'some-script.js',
callback: function() {
// do some code here
},
},
{
file : 'another-script.js',
callback: function() {
// do some code here
},
},
...
]
};
如果可能,我该如何自动执行此操作?
答案 0 :(得分:2)
(我假设您正在使用JSONP加载外部脚本)您将面临的问题是这些脚本不会同时加载所有脚本。
下面是一些代码,一旦加载了相关的脚本,它就会调用你的回调函数。
function include_js(url, callback) { // http://www.nczonline.net
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) { //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
//Edit
for (var i = 0; i < data.scripts.length; i++) {
include_js(data.scripts[i].file, data.scripts[i].callback);
}
答案 1 :(得分:1)
可能如果,您可以在每个脚本中测试一个符号,或者每个脚本在加载完成后都可以执行函数调用。
加载脚本很简单,我相信你知道:
var script = document.createElement('script');
script.src = /* ... the source path ... */;
document.body.appendChild(script);
(相反,您会看到有人追加到head
;无关紧要,body
很容易找到。)
但困难的部分是知道何时下载并执行。唯一真正的方法是通过轮询来查看脚本定义的新全局符号是否已定义,或者让脚本在加载完成后主动回叫(a'la JSONP)。 / p>
无论哪种方式,一旦您检测到符号或获得回调,您就可以继续加载下一个脚本。
这是一个快速而又脏的草图,它是在找到全局符号(window
对象上的属性)的基础上进行的:
// The scripts to load
var scriptList = {
scripts: [
{
file : 'some-script.js',
callback: function() {
// do some code here
},
symbol : "someSymbol",
timeout : 30000 // We know this one is slow, give it 30 seconds
},
{
file : 'another-script.js',
callback: function() {
// do some code here
},
symbol : "anotherSymbol"
},
// ...
]
};
// Triggering the load
loadScripts(scriptList);
// Library routines to do the load
function loadScripts(list)
{
var index, timeout;
// Start with the first one (loadNextScript starts with an increment)
index = -1;
loadNextScript();
// This function loads the next script in the list; if there are no
// more, it simply returns
function loadNextScript()
{
var script;
// Are there more?
++index;
if (index < list.length)
{
// Yes, append a `script` element
script = document.createElement('script');
script.src = list.file;
document.body.appendChild(script);
// Determine when to time out
timeout = new Date() + (list[index].timeout || 20000); // Time out in Xms, default 20 seconds
// Start polling
setTimeout(pollForScript, 0); // Async, but almost immediately (4-10ms on most browsers)
}
}
// This function polls to see if the current script has loaded yet by
// checking for a global symbol it defines.
function pollForScript()
{
var result;
// Has it been too long?
if (new Date() > timeout)
{
// Yes
result = "timeout";
}
else
{
// Has the symbol been defined?
if (typeof window[list[index].symbol] !== "undefined")
{
// Yes
result = "loaded";
}
else
{
// Nope, keep waiting
setTimeout(pollForScript, 250); // Check every quarter-second
}
}
// Did we get a result?
if (result)
{
// Yes, do the callback telling it of the result
try {
list[index].callback(result);
}
catch (e) {
}
// Load the next script
loadNextScript();
}
}
}
答案 2 :(得分:0)
让回调调用你的loadTheNextScriptInList
或任何函数。您可以通过向onLoad事件添加匿名函数来自动执行此操作。此匿名函数应首先调用列表中的回调集,然后调用loadTheNextScriptInList
函数。
答案 3 :(得分:0)
这只是我写的快速和HAVENT TESTED,但它应该以递归的方式完成你的工作。希望这会有所帮助:
var data = {
scripts: [
{
file : 'some-script.js',
callback: function() {
// do some code here
},
},
{
file : 'another-script.js',
callback: function() {
// do some code here
},
},
...
]
};
$(document).ready(function() {
if(data.scripts.length > 0) {
scriptLoader(0);
}
});
function scriptLoader(i) {
var currScript = data.scripts[i];
$.getScript(currScript.file, function() {
// execute your callback
currScript.callback();
// load next script
if(i < data.scripts.length) {
scriptLoader(i++);
}
});
}
哦,顺便说一句,这使用了JQuery javascript框架,仅供参考。