Повторяющийся код "Outsource" в функцию с параметрами (js)
Поэтому я использую один файл js для загрузки нескольких файлов html и js всякий раз, когда они необходимы. У меня есть рабочий код для множества модулей. В приведенном ниже примере вы можете увидеть первые два модуля. Все они выглядят одинаково. Теперь я хочу "перевести" повторяющийся код в функцию с параметрами, чтобы общий объем кода был минимизирован. Так как я никогда не делал что-то подобное раньше, мне могла бы понадобиться некоторая помощь (сейчас я изучаю js). Я был бы очень признателен за помощь.
//first module
if (moduleID === "placeone") {
var isLoaded = 0;
if (isLoaded) {
console.log("file already loaded");
returnValue = new PlaceOneModule(id, moduleInitialData);
}
$("#placeone").load("html/modules/PlaceOneModule.html", function (response, status, xhr) {
console.log("PlaceOneModule.html" + " " + status);
$.getScript("js/modules/PlaceOneModule.js").done(function () {
console.log("PlaceOneModule.js geladen");
isLoaded = 1;
returnValue = new PlaceOneModule(id, moduleInitialData);
}).fail(function () {
console.log("PlaceOneModule.js nicht geladen");
});
});
}
//second module
if (moduleID === "placetwo") {
var isLoaded = 0;
if (isLoaded) {
console.log("file already loaded");
returnValue = new PlaceTwoModule(id, moduleInitialData);
}
$("#placetwo").load("html/modules/PlaceTwoModule.html", function (response, status, xhr) {
console.log("PlaceTwoModule.html" + " " + status);
$.getScript("js/modules/PlaceTwoModule.js").done(function () {
console.log("PlaceTwoModule.js geladen");
isLoaded = 1;
returnValue = new PlaceTwoModule(id, moduleInitialData);
}).fail(function () {
console.log("PlaceTwoModule.js nicht geladen");
});
});
}
2 ответа
На вопрос довольно сложно ответить, так как есть много вещей, которые нужно учитывать.
var cache = {};
function module(name, target, done) {
if (!(name in cache)) {
return $(target).load('html/modules/' + name + '.html', function(response, status, xhr) {
console.log(name + '.html ' + status);
$.getScript('js/modules/' + name + '.js')
.done(function() {
console.log(name + '.js geladen');
cache[name] = window[name];
done(null, cache[name]);
})
.fail(function() {
var message = name + '.js nicht geladen';
cache[name] = function() {
console.error(message);
};
done(message);
});
});
}
setTimeout(function() {
done(null, cache[name]);
}, 0);
}
Я постараюсь объяснить мой ход мыслей за этим:
var cache = {}
- вам нужно что-то, чтобы отслеживать каждый отдельный модульfunction module(name, target, done) {
name
будет базовым именем вашего модуля, напримерPlaceTwoModule
это уже использовалось последовательно в файлах html и js и имени функции jstarget
будет селектором, в который должен быть загружен HTML-файл- поскольку одно из действий, которые вы выполняете, требует асинхронной операции, все функции должны стать асинхронными, я ввожу обратный вызов (
done
) аргумент
if (!(name in cache))
- если модуль еще не кэширован, он требует выборки, поэтомуload
срабатывает первым делом- однажды
load
завершает, он уволит$.getScript
- если
$.getScript
работает,name
будет считаться вwindow
и ссылка хранится вcache
переменная, после этогоdone
обратный вызов вызывается (с функцией в качестве второго аргумента). - если
$.getScript
не получилось, мы добавили функцию кcache
который ничего не делает, кроме как сказать вам, что это не сработает, после этогоdone
обратный вызов вызывается (с ошибкой в качестве первого аргумента).
- если
- если
name
существовал вcache
мы будем называтьdone
обратный вызов сразу после выхода изmodule
функция
Итак, как это использовать? Теперь все сводится к module
функция
module('#placeone', 'PlaceOneModule', function(error, PlaceModule) {
if (error) throw new Error(error);
var instance = new PlaceModule(id, initial);
// ...
}
Я использовал общий function(error, value) {..}
подпись для функции обратного вызова, которая всегда имеет ошибку в качестве первого аргумента (что позволяет добавлять и аргументировать другие аргументы).
Есть некоторые предостережения / предположения, которые стоит упомянуть:
- Я не предоставил отказоустойчивый для предотвращения нескольких загрузок одного и того же модуля (так же, как в вашем примере), если ранее звонки
module
все еще загружаются - не важно что
target
Вы вызываетеmodule
с, он загрузится только один раз (ну, смотрите предыдущую строку;-)) - Я предполагаю, что загруженные модули находятся в глобальном (
window
) для того, чтобы пример был простым, имейте в виду, что "не загрязняйте глобальный охват"
Это стало довольно сложным ответом, я надеюсь, что объяснил каждый шаг достаточно.
Что-то вроде этого возможно:
var modules = [];
modules.push({
js: 'PlaceOneModule',
id: 'placeone'
});
modules.push({
js: 'PlaceTwoModule',
id: 'placetwo'
});
var module = modules.filter(function(m) {
return m.id === moduleID;
});
if (module) {
var isLoaded = 0;
if (!!window[module.js]) {
console.log("file already loaded");
returnValue = window[module.js];
}
$("#" + module.id).load("html/modules/" + module.js + ".html", function(response, status, xhr) {
$.getScript("js/modules/" + module.js + ".js").done(function() {
returnValue = new window[module.js](id, moduleInitialData);
}).fail(function() {
console.log("PlaceOneModule.js nicht geladen");
});
});
}