我尝试编写一个加载js脚本(src
)的JavaScript函数,并在加载脚本时执行一些回调。
我还会查看是否已存在具有相同src
的脚本。
我的问题是如果脚本已经加载,则不会执行回调。那是NOK。
如何知道脚本是否已加载?
importScript: (function (head) {
function loadError(error) {
throw new URIError("The script " +
error.target.src + " is not accessible.");}
return function (url, callback) {
var existingScript = document.querySelectorAll("script[src='" +
url + "']");
var isNewScript = (existingScript.length == 0);
var script;
if (isNewScript) {
script = document.createElement("script")
script.type = "text/javascript";
}
else {
script = existingScript[0];
}
script.onerror = loadError;
if (script.readyState) { //IE
script.onreadystatechange = function () {
if (script.readyState == "loaded" ||
script.readyState == "complete") {
script.onreadystatechange = null;
if (callback) {
callback(); }
}
};
} else { // others than IE
script.onload = callback; }
if (isNewScript) {
script.src = url;
head.appendChild(script); }
}
})(document.head || document.getElementsByTagName("head")[0])
据我了解,script.readyState == "loaded" || script.readyState == "complete"
只适用于IE ,而不适用于其他浏览器......
用法:
importScript("myScript1.js");
importScript("myScript2.js", /* onload function: */
function () { alert("The script has been OK loaded."); });
答案 0 :(得分:6)
我推荐jQuery,它很容易。生活对于像你自己这样的事情来说太短了(你会浪费时间来支持所有的浏览器)。
$.ajax({
url: "/script.js",
dataType: "script",
success: function() {
console.log("script loaded");
}
});
编辑:
它更容易(例如来自jQuery docs):
$.getScript( "ajax/test.js", function( data, textStatus, jqxhr ) {
console.log(data); // Data returned
console.log(textStatus); // Success
console.log(jqxhr.status); // 200
});
您还可以链接已完成和失败以进行其他回调:
$.getScript("ajax/test.js")
.done(function(script, textStatus) {
console.log(textStatus);
})
.fail(function(jqxhr, settings, exception) {
console.log("loading script failed.");
});
<script src="path/to/jquery"></script>
<script>
function wait(method) {
if (window.$) {
method();
} else {
setTimeout(function () { wait(method); }, 100); // check every 100ms
}
}
// wait for jQuery
wait(function() {
// jQuery has loaded!
$("#foo").doSomething();
// you can now load other scripts with jQuery:
$.getScript("ajax/test.js")
.done(function(script, textStatus) {
console.log(textStatus);
})
.fail(function(jqxhr, settings, exception) {
console.log("loading script failed.");
});
}
</script>
答案 1 :(得分:1)
检查脚本是否加载的最安全方法是,您可以在脚本末尾添加一个简单的回调。如果存在,可以调用哪些数据也可以传递。
if(window.loaded){
window.loaded(params);
}
一旦脚本加载,它将执行此方法,您可以在父脚本中声明该方法将被调用。
此外,您可以在正文上触发事件并在其他父代码中侦听该事件。
答案 2 :(得分:0)
基于Luca Steeb的方法,我将解决方案精简为仅两个脚本标签,对于SPA应用程序,index.html具有以下特点:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Simplified INDEX</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="/bootloader.js"></script>
</head>
<body>
</body>
</html>
bootloader.js,结合了Luca和load css using jquery的想法:
function loadScripts() {
// jQuery has loaded!
console.log("jquery is loaded");
// you can now load other scripts and css files with jQuery:
$.when($.getStylesheet('css/main.css'), $.getScript('js/main.js'))
.then(function () {
console.log('the css and js loaded successfully and are both ready');
}, function () {
console.log('an error occurred somewhere');
});
}
function patchGetStylesheet($) {
$.getStylesheet = function (href) {
var $d = $.Deferred();
var $link = $('<link/>', {
rel: 'stylesheet',
type: 'text/css',
href: href
}).appendTo('head');
$d.resolve($link);
return $d.promise();
};
}
function wait(method) {
if (window.$) {
patchGetStylesheet(window.$);
method();
} else {
setTimeout(function () {
wait(method);
}, 100); // check every 100ms
}
}
// wait for jQuery
wait(loadScripts);
对于bootloader.js,可以使用webpack对其进行缩小,混淆...
我们不再通过使用jquery解决运行时依赖性将代码添加到index.html。