Я использую шаблон модуля, одна из вещей, которые я хочу сделать, динамично включают внешний файл JavaScript, выполняют файл и затем используют функции/переменные в файле в return { }
из моего модуля.
Я не могу выяснить, как сделать это легко. Есть ли какие-либо стандартные способы выполнить псевдо синхронную внешнюю загрузку сценария?
function myModule() {
var tag = document.createElement("script");
tag.type = "text/javascript";
tag.src = "http://some/script.js";
document.getElementsByTagName('head')[0].appendChild(tag);
//something should go here to ensure file is loaded before return is executed
return {
external: externalVariable
}
}
У меня была подобная задача несколькими днями ранее, и вот то, как я сделал это.
Этот загрузчик работает и в file://
префиксы, а также в http://
и https://
и является совместимым перекрестным браузером.
Это однако, не может загрузить определенные классы или функции как модули из сценариев; это загрузит целый сценарий в целом и сделает это доступным для DOM.
// Loads a script or an array of scripts (including stylesheets)
// in their respective index order, synchronously.
// By Sayanjyoti Das @https://stackoverflow.com/users/7189950/sayanjyoti-das
var Loader={
queue: [], // Scripts queued to be loaded synchronously
loadJsCss: function(src, onl) {
var ext=src.toLowerCase().substring(src.length-3, src.length);
if(ext=='.js') {
var scrNode=el('script', null, null, null);
scrNode.type='text/javascript';
scrNode.onload=function() {onl();};
scrNode.src=src;
document.body.appendChild(scrNode);
}else if(ext=='css') {
var cssNode=el('link', null, null, null);
cssNode.rel='stylesheet';
cssNode.type='text/css';
cssNode.href=src;
document.head.appendChild(cssNode);
onl();
}
},
add: function(data) {
var ltype=(typeof data.src).toLowerCase();
// Load a single script
if(ltype=='string') {
data.src=data.src;
Loader.queue.splice(0, 1, data, Loader.queue[0]);
Loader.next();
}
// Load an array of scripts
else if(ltype=='object') {
for(var i=data.src.length-1; i>=0; i--) {
Loader.queue.splice(0, 1, {
src: data.src[i],
onload: function() {
if(Loader.next()==false) {
data.onload();
return;
}
Loader.next();
}
}, Loader.queue[0]);
}
Loader.next();
}
},
next: function() {
if(Loader.queue.length!=0 && Loader.queue[0]) {
var scr=Loader.queue[0];
// Remove the script from the queue
if(Loader.queue.length>1)
Loader.queue.splice(0, 2, Loader.queue[1]);
else
Loader.queue=[];
// Load the script
Loader.loadJsCss(scr.src, scr.onload);
}else return false;
}
};
вышеупомянутая функция очень мощна и изящна ; это позволяет Вам загружать единственный сценарий или массив сценария синхронно (т.е., следующий сценарий, не загруженный до предыдущей законченной загрузки сценария). Кроме того, загруженный сценарий может загрузить больше сценариев, который задерживает очередь в родительском сценарии.
BTW, сценарий здесь означает файл JavaScript или таблицу стилей CSS .
Вот то, как использовать Примечание it:-
// Load a single script
Loader.add({
src: 'test.js',
onload: function() {
alert('yay!');
}
});
// Load multiple scripts
Loader.add({
src: ['test1.js', 'test2.js', 'mystyles.css', 'test3.js'],
onload: function() {
alert('all loaded!');
}
});
, что, эти onload
функция в аргументах Загрузчика вызвана, когда весь из сценариев загрузились, не, когда один или единственный сценарий загружается.
можно также загрузить больше сценариев в сценариях, которые Вы загрузили, такой как в test.js
, test1.js
, и т.д. Путем выполнения этого, Вы задержите загрузку следующего родительского сценария, и очередь в дочернем сценарии будет расположена по приоритетам.
Hope это помогает :-)
вот мой код
var loaded_script = [];
function loadScript(urls, callback, sync) {
var len = urls.length, count = 0;
// check are all js loaded, then execute callback (if any)
var check = function() {
if (count == len) {
callback && typeof callback=="function" && callback();
}
};
for (var i = 0; i < len; i++) {
var url = urls[i];
// check if script not loaded (prevent load again)
if (loaded_script.indexOf(url) == -1) {
var script = document.createElement("script");
script.type = "text/javascript";
// set sync loading here (default is async)
if (sync) {
script.async = false;
}
// script onload event
if (script.readyState) { // IE
script.onreadystatechange = function() {
if (script.readyState=="loaded" || script.readyState=="complete") {
script.onreadystatechange = null;
count++, check();
}
};
} else { // Others
script.onload = function() {
count++, check();
};
}
// add script to head tag
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
// mark this script has loaded
loaded_script.push(url);
} else {
count++, check();
}
}
}
, я использую это на pjax сайте.
loadScript(
[
"js/first.js",
"js/second.js",
],
function() {
alert("Scripts loaded.");
},
true
);