Базопасный placeholder-болванка javascript ответа
На сервере динамически генерируется javascript ответ (допустим script.js). При этом какая-то часть файла — статическая и одинаковая для всех клиентов, а какая-то должна быть заменена для каждого клиента отдельно. При этом заменой занимается некий серверный язык. Задача: предоставить файл-шаблон, в определенное место в котором будут подставляться данные. Первое, что приходит на ум выглядит как-то так:
(function () {
var data = #DATA_PLACEHOLDER#;
var errors = #ERRORS_PLACEHOLDER#;
var all = {};
all.data = data;
all.errors = errors;
window.provide = processData(all);
}());
Файл получается невалидным, что влечет ряд последствий:
- Его валидацию надо исключить из общей валидации проекта, или реализовывать отдельную.
- При исключении файла из валидации велик шанс синтаксической ошибки при последующей его правке (сборка проекта пройдет успешно, но клиентская часть не отработает)
- В случае отказа бекэнда инициализация не произойдет, и код, зависящий от кода в файле, что мы генерируем, завалится, обращаясь к необъявленной переменной (provide).
Явно напрашивается, что плейсхолдером должен быть особой формы комментарий, при это должна быть альтернатива, в случае, если комментарий не заменится на значение. Вот-же ж оно: использем самовызывающиеся анонимные функции:
(function () {
var data = (function () {return /*!DATA_PLACEHOLDER*/})() || {};
var errors = (function () {return /*!ERRORS_PLACEHOLDER*/})() || [];
var all = {};
all.data = data;
all.errors = errors;
window.provide = processData(all);
}());
Уже намного лучше. Файл валиден, теперь его можно не исключать из процесса проверки всего проекта. А так-же в случае с проблемами на бекэнде, клиентская часть продолжает инициализироваться. Тут она сможет сама решить, как поступать в случае падения серверов.
Однако не все так безрадостно.
var data = (function() {return
{
importantValue: true
}
})() || {};
console.log(data.importantValue); // undefined
Стоит вставить данные, начиная с перевода строки, как вся стройная система рассыпется. Конечно можно организационно решить вопрос, сказав явно программисту, чтобы данные начинались с символа, но это не наш путь, да и организационные методы действуют плохо.
И вот оно, финальное решение: передадим данные аргументом, и вернем их-же.
(function () {
var data = (function (data) {return data})(/*!DATA_PLACEHOLDER*/) || {};
var errors = (function (errors) {return errors})(/*!ERRORS_PLACEHOLDER*/) || [];
var all = {};
all.data = data;
all.errors = errors;
window.provide = processData(all);
}());
На выходе — пуленепробиваемая, валидная конструкция для последующего наполнения данными.