Техника динамической загрузки данных через XHR (в простонародии, AJAX ) очень популярна в современном WEB-е. Но вот динамическую загрузку программных компонент используют пока крайне редко. Компактный модуль ScriptLoader наглядно демонстрирует то, как это может быть просто и функционально.
/**
* JavaScript loader
* @param modules {Array} массив имен js файлов
*/
var ScriptLoader = function (modules) {
this.modules = modules.slice();
this.queue = new Queue();
this._init();
};
ScriptLoader.prototype = {
run: function () {
// test for header ready
var head = document.getElementsByTagName("head");
if (head.length > 0) {
this.queue.iterate();
} else {
setTimeout(arguments.callee, 500);
}
},
_init: function () {
var i, me = this;
for (i = 0; i < me.modules.length; i++) {
(function (name) {
me.queue.add(function () {
var head, script;
head = document.getElementsByTagName("head");
if (head.length > 0) {
head = head[0];
script = document.createElement("script");
script.src = name;
script.type = "text/javascript";
script.onload = script.onreadystatechange = function () {
if ((!this.readyState || this.readyState == "loaded" || this.readyState == "complete") ) {
me.queue.iterate();
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
};
head.appendChild(script);
}
});
})(me.modules[i]);
}
}
};
Обратите внимание, что в этом модуле используется Queue.
Пример использования.
var loader = new ScriptLoader(["file1.js", "file2.js", "http://server.org/js/framework.js"]);
// на этом этапе в очередь могут быть добавлены дополнительные вызовы
loader.queue.add(function () {
Module1.init();
});
loader.run();
Коментарии к заметке
Можно улучшить добавляя скрипты не в head, а после последнего тега script. Head на странице может не быть, а как минимум один script точно будет (сам динамический загрузчик).
Согласен. Как раз такая техника и применяется в yepnope.js . Его сейчас сам использую для этих нужд. И даже больше — написал специально под API yepnope.js систему обслуживания зависимостей ресурсов (теперь это часть моего маленького фреймворка «Скелет приложения»).