Я пытаюсь понять подход функционального программирования. Насколько я понимаю, это в основном инкапсуляция всего в функции и их передача. Теперь для моего примера я пытаюсь загрузить данные из RESTApi и отобразить их в DOM:
const storyElement = function (): HTMLElement {
const div = document.createElement('div');
div.className = 'stories';
return div;
};
const spinnerElement = function (): HTMLElement {
const div = document.createElement('div');
div.className = 'spinner';
div.innerHTML = `<svg class = "spinner" viewBox = "0 0 100 100" width = "20" height = "20">
<circle cx = "50" cy = "50" r = "42" transform = "rotate(-90,50,50)" />
</svg>`;
return div;
};
У меня есть два блока: один для историй и один для значка загрузки. Если содержимое отображается, значок должен исчезнуть.
function getAllStories(callback): void {
makeRequest(baseUrl(), (res) => spawn(res, callback));
}
function spawn(content, callback): void {
content = JSON.parse(content);
if (content instanceof Array === false) {
content = [content];
}
content.forEach(elm =>
storyElement().innerHTML += `<h1>${elm.title}</h1>
<div class = "story-info">
<i>ID: Post-${elm.id}</i>
</div>
<p>${elm.body}.</p>`
);
console.info(content);
callback();
}
function displayFinished(): void {
spinnerElement().style.display = 'none';
document.body.innerHTML += '<div>All done!</div>';
}
Теперь, когда я выполняю getAllStories, консоль выводит результат, но содержимое не отображается в DOM:
document.body.appendChild(storyElement());
document.body.appendChild(spinnerElement());
getAllStories(displayFinished);
Кто-нибудь знает, почему?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Каждый раз, когда вы вызываете storyElement() в своем .forEach, создается новый элемент. Вы никогда не меняли исходный элемент, который вы прикрепили к DOM.
Благодаря @dnt я решил свою проблему. Решение состоит в том, чтобы создать элемент и вложить эту функциональность: получить данные из RESTAPI => создать его в DOM => завершить отображение значка загрузки.
function createElm(className: string, innerHTML?: string): Node {
const div = document.createElement('div');
div.className = className;
if (innerHTML) {
div.innerHTML = innerHTML;
}
document.body.appendChild(div);
return div;
}
function getAllStories(callback): void {
makeRequest(baseUrl(), callback);
}
function spawn(content, html, callback): void {
content = JSON.parse(content);
if (content instanceof Array === false) {
content = [content];
}
content.forEach(elm =>
html.innerHTML += `<h1>${elm.title}</h1>
<div class = "story-info">
<i>ID: Post-${elm.id}</i>
</div>
<p>${elm.body}.</p>`
);
callback();
}
function displayFinished(html): void {
html.style.display = 'none';
document.body.innerHTML += '<div>All done!</div>';
}
const stories = createElm('stories');
const loadingIcon = createElm('spinner', `<svg class = "spinner" viewBox = "0 0 100 100" width = "20" height = "20">
<circle cx = "50" cy = "50" r = "42" transform = "rotate(-90,50,50)" />
</svg>`);
getAllStories(res =>
spawn(res, stories, () =>
displayFinished(loadingIcon)));
Сейчас я просто спрашиваю себя, есть ли лучший вариант для моего подхода. Мне кажется неправильным не использовать простые переменные для dom-элементов ...
Это не реальный проект, просто попробуйте протестировать подход обратного вызова, не хотел заходить так далеко, но спасибо за совет! :)
Вы не должны изменять DOM в цикле (
html.innerHTML += ...), который вызывает перерасчет макета каждый раз. Кроме того, использование такой интерполяции простой строки открывает вам всевозможные неприятные проблемы, такие как недопустимые атаки HTML и XSS. Рекомендую использовать какую-то библиотеку шаблонов.