如果像这样在头部注入多个脚本标签并混合本地和远程脚本文件,则可能会出现依赖外部脚本的本地脚本(例如从 googleapis 加载 jQuery)会出现错误的情况,因为外部脚本可能不是在本地加载之前加载。
所以这样的事情会有一个问题:(jquery.some-plugin.js 中的“jQuery is not defined”)。
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js";
head.appendChild(script);
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "/jquery.some-plugin.js";
head.appendChild(script);
当然,这种情况是 .onload() 的用途,但是如果要加载多个脚本,这可能会很麻烦。
作为对这种情况的解决方案,我将这个函数放在一起,它将保留要加载的脚本队列,在前一个完成后加载每个后续项目,并返回一个 Promise,当脚本(或队列中的最后一个脚本,如果无参数)完成加载。
load_script = function(src) {
// Initialize scripts queue
if( load_script.scripts === undefined ) {
load_script.scripts = [];
load_script.index = -1;
load_script.loading = false;
load_script.next = function() {
if( load_script.loading ) return;
// Load the next queue item
load_script.loading = true;
var item = load_script.scripts[++load_script.index];
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = item.src;
// When complete, start next item in queue and resolve this item's promise
script.onload = () => {
load_script.loading = false;
if( load_script.index < load_script.scripts.length - 1 ) load_script.next();
item.resolve();
};
head.appendChild(script);
};
};
// Adding a script to the queue
if( src ) {
// Check if already added
for(var i=0; i < load_script.scripts.length; i++) {
if( load_script.scripts[i].src == src ) return load_script.scripts[i].promise;
}
// Add to the queue
var item = { src: src };
item.promise = new Promise(resolve => {item.resolve = resolve;});
load_script.scripts.push(item);
load_script.next();
}
// Return the promise of the last queue item
return load_script.scripts[ load_script.scripts.length - 1 ].promise;
};
有了这个添加脚本,以确保在盯着下一个之前完成前一个可以像......
["https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js",
"/jquery.some-plugin.js",
"/dependant-on-plugin.js",
].forEach(load_script);
或者加载脚本并在完成后使用 return Promise 来完成工作......
load_script("some-script.js")
.then(function() {
/* some-script.js is done loading */
});