Задать вопрос
@FlatUser

SetTimeout 0, костыль ли и чем заменить?

У меня есть функция которая создаёт клон элемента вставляет/вычисляет ширину и отдаёт коллбеком.

Три последние строчки:
body.append(clone);
let cloneWidth = document.querySelector('.clone').offsetWidth;
callback(cloneWidth);


Проблема в том что в коллбэк приходят неверные данные ширины.
Клон довольно большой/вложенный у меня есть догадки о том что он просто полностью не успевает отрендерится.

Данную проблему решает callback внутри setTimeout со значением 0;

Прочитав ответы на стэковерфлоу с гугл переводчиком, ответа о том правильно ли это вообще я не нашёл.

Усердно прошу господина/госпожу объяснить мне в чем дело такого поведения js и правильности использования setTimeout 0;
  • Вопрос задан
  • 5801 просмотр
Подписаться 3 Простой 2 комментария
Решения вопроса 3
По существу костыль, т.к. setTimeout(0) просто заставляет функцию вызваться в конце очереди событий, которая в синхронном JS одна. Если не знать, как работает JS, выглядит как черная магия. Обойти могу предложить лишь одним путем, который и видится мне единственно верным: переосмыслением архитектуры.

Во-первых, почему бы не использовать virtual dom и вычислять все до того, как элемент вставится в DOM?
Во-вторых, почему бы не использовать кастомные события, на которых и построить все взаимодействия? Называется event-driven architecture, EDA. Как только скопируете, вычислите и проверите, триггерите событие `element-loaded` и по событию уже вставляете в DOM.
В-третьих, почему бы не брать ширину и высоту элемента, которого клонируем? Тогда вообще все мгновенно будет. Не совсем ясен смысл получения ширины \ высоты склонированного элемента, если учесть, что они одинаковые должны быть у оригинала и клона.
Ответ написан
@abberati
frontend-разработчик
Неправильная ширина приходит из-за того, что сам рендер происходит после того, как опустошится стек вызовов в js (гуглите event loop).

setTimeout(, 0) — не самый очевидный, но рабочий ход, который откладывает вычисление ширины на следующий тик event loop. Попробуйте MutationObserver, может помочь (сам с ним никогда не работал).
Ответ написан
Комментировать
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Так возвращайте ширину по событию готовности отрисовки (рендринга) элемента (а не "в лоб", как сейчас).
MutationObserver с примером: здесь.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы