Как сразу применить модификации DOM с JS? - PullRequest
0 голосов
/ 05 мая 2019

У меня есть функция Javascript, которая требует немного времени для обработки. Во время выполнения этой функции JS я показываю некоторый текст (и / или применяю модальное наложение), а затем после выполнения показываю результаты на странице. Бывает, что отображается только окончательный текст, а все изменения текста в процессе - нет. Таким образом, в основном вопрос заключается в следующем: почему видна / применена только последняя модификация DOM, а все остальные предыдущие модификации нет? Ниже приведен небольшой пример, объясняющий, что я имею в виду.

<!DOCTYPE html>
<html>
    <head>
        <style>
            #modal-overlay{position: absolute;left: 0; top: 0; right: 0; bottom: 0;z-index: 2;background-color: rgba(255,255,255,0.7);}
            #modal-overlay-content {position: absolute; transform: translateY(-50%); -webkit-transform: translateY(-50%); -ms-transform: translateY(-50%); top: 50%; left: 0; right: 0; text-align: center;}
        </style>
        <script>
            function test() {
                step1();
                step2();
                step3();
            }

            function step1() {
                document.getElementById("modal-overlay").style.display = "inline";
                document.getElementById("paragraph").innerText = "Do you see this text?";
            }

            function step2() {
                // do nothing for 5000ms
                var now = new Date().getTime();
                while (new Date().getTime() < now + 5000) { /* do nothing */ }
            }

            function step3() {
                document.getElementById("modal-overlay").style.display = "none";
                document.getElementById("paragraph").innerText = "Only this text is shown at the end of the process";
            }
        </script>
    </head>
    <body>
        <div id="modal-overlay" style="display: none;"><div id="modal-overlay-content"><h1>Loading...</h1></div></div>
        <p id="paragraph"></p>
        <input type="submit" value="Push" onclick="test()" />
    </body>
</html>

Ответы [ 2 ]

0 голосов
/ 05 мая 2019

Правильный способ сделать то, что вы хотите, заключается в следующем:

function test() {
    step1();
    setTimeout(step3, 5000);
}

function step1() {
    document.getElementById("modal-overlay").style.display = "inline";
    document.getElementById("paragraph").innerText = "Do you see this text?";
}

function step3() {
   document.getElementById("modal-overlay").style.display = "none";
    document.getElementById("paragraph").innerText = "Only this text is shown at the end of the process";
}

Разница в том, что setTimeout является "асинхронным". Он позволяет другому коду продолжать работу и возвращается к выполнению функции, которую вы ему предоставили (здесь step3) после истечения желаемого интервала времени.

Ваша исходная версия пытается "подождать" в течение 5 секунд "синхронно" - в основном заставляя код выполнять пустой цикл и проверять временную метку на каждой итерации, пока не пройдет достаточно времени. В течение этого времени выполняется код - код, который сам по себе не имеет наблюдаемого эффекта, но, тем не менее, код все еще выполняется. Поскольку Javascript является однопоточным, это останавливает что-либо еще на странице. В частности, он останавливает обновления DOM, поэтому ваш код не работает так, как вы ожидали.

Еще серьезнее, однако, он вообще не позволяет пользователям взаимодействовать с браузером - независимо от того, пытаются ли они что-то щелкнуть, прокрутить страницу или что-то еще, браузер может показаться полностью не отвечающим. И это главная причина, почему вы всегда должны использовать асинхронные функции для таких целей, а не создавать искусственный цикл, чтобы остановить что-либо происходящее.

0 голосов
/ 05 мая 2019

Вы должны использовать setTimeout, чтобы запланировать функцию, не заняты ожиданием.

function test() {
    step1();
    setTimeout(step3,5000)
}

function step1() {
    document.getElementById("modal-overlay").style.display = "inline";
    document.getElementById("paragraph").innerText = "Do you see this text?";
}

function step3() {
    document.getElementById("modal-overlay").style.display = "none";
    document.getElementById("paragraph").innerText = "Only this text is shown at the end of the process";
}
<html>
    <head>
        <style>
            #modal-overlay{position: absolute;left: 0; top: 0; right: 0; bottom: 0;z-index: 2;background-color: rgba(255,255,255,0.7);}
            #modal-overlay-content {position: absolute; transform: translateY(-50%); -webkit-transform: translateY(-50%); -ms-transform: translateY(-50%); top: 50%; left: 0; right: 0; text-align: center;}
        </style>
        <script>

        </script>
    </head>
    <body>
        <div id="modal-overlay" style="display: none;"><div id="modal-overlay-content"><h1>Loading...</h1></div></div>
        <p id="paragraph"></p>
        <input type="submit" value="Push" onclick="test()" />
    </body>
</html>

Допустим, если у вас нет веских причин, не используйте фиксированную длительность режим загрузки.Загрузите свой ресурс и зарегистрируйте обратный вызов для его завершения.

...