不是重复的,因为我还没有在其他线程上找到令人满意的答案:
- Load and execute javascript code SYNCHRONOUSLY
- Loading HTML and Script order execution
- Load and execute javascript code SYNCHRONOUSLY
请寻找原生 Javascript 答案,没有 jQuery,没有 requireJS,等等 :)
整个问题的总结:
我想异步加载脚本但是已经有序执行
我试图强制插入的脚本元素中的代码完全按照添加到 dom 树的相同顺序执行。
也就是说,如果我插入两个脚本标签,第一个和第二个,第一个中的任何代码都必须在第二个之前触发,无论谁先完成加载。
我在插入头部时尝试使用 async 属性和 defer 属性,但似乎不服从。
我尝试过 element.setAttribute("defer", "") 和 element.setAttribute("async", false) 以及其他组合。
我目前遇到的问题是在包含外部脚本时必须解决的问题,但这也是我在存在延迟的情况下执行的唯一测试。
第二个脚本是本地脚本,总是在第一个脚本之前触发,即使它是在之后插入到 dom 树 ( head ) 中的。
A) 请注意 我仍在尝试将两个脚本元素插入到 DOM 中。当然上面可以通过先插入来实现,让它完成并插入第二个,但我希望有另一种方法,因为这可能很慢。
我的理解是 RequireJS 似乎就是在做这个,所以应该是可以的。然而,requireJS 可能会按照 A 中的描述完成它。
如果您想直接在 firebug 中尝试代码,只需复制并粘贴:
function loadScript(path, callback, errorCallback, options) {
var element = document.createElement('script');
element.setAttribute("type", 'text/javascript');
element.setAttribute("src", path);
return loadElement(element, callback, errorCallback, options);
}
function loadElement(element, callback, errorCallback, options) {
element.setAttribute("defer", "");
// element.setAttribute("async", "false");
element.loaded = false;
if (element.readyState){ // IE
element.onreadystatechange = function(){
if (element.readyState == "loaded" || element.readyState == "complete"){
element.onreadystatechange = null;
loadElementOnLoad(element, callback);
}
};
} else { // Others
element.onload = function() {
loadElementOnLoad(element, callback);
};
}
element.onerror = function() {
errorCallback && errorCallback(element);
};
(document.head || document.getElementsByTagName('head')[0] || document.body).appendChild(element);
return element;
}
function loadElementOnLoad(element, callback) {
if (element.loaded != true) {
element.loaded = true;
if ( callback ) callback(element);
}
}
loadScript("http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js",function() {
alert(1);
})
loadScript("http://ajax.googleapis.com/ajax/libs/chrome-frame/1.0.3/CFInstall.min.js",function() {
alert(2);
})
如果你像 Firebug 一样尝试上面的代码,它通常会触发 2,然后是 1。我想确保先是 1,然后是 2,但两者都包含在头部。
最佳答案
if I insert two script tags, first and second, any code in first must fire before the second, no matter who finishes loading first. I have tried with the async attribute and defer attribute
不,async
和 defer
在这里帮不了你。每当您将脚本元素动态插入 DOM 时,它们都会异步加载和执行。你对此无能为力。
My understanding is that RequireJS seems to be doing just this
没有。即使使用 RequireJS,脚本也是异步执行的,而不是按顺序执行的。只有那些脚本中的模块初始化函数只是define()
d,没有被执行。然后,Requirejs 确实会在满足它们的依赖关系时进行查找,并在稍后加载其他模块时执行它们。
当然你可以重新发明轮子,但你必须使用类似 requirejs 的结构。
关于Javascript,按顺序执行脚本代码插入dom树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17978255/