Дождитесь завершения всех обновлений dom - PullRequest
0 голосов
/ 01 мая 2020

У меня есть страница с несколькими загрузочными счетчиками, которые необходимо отобразить. Я поместил их в функцию, которую я вызываю, когда они мне нужны (есть противоположная функция для их скрытия). Я хочу, чтобы мои счетчики отображались на событии изменения для поля выбора css. Идентификатор находится на элементе выбора. Сразу же после появления этих блесен следует длительный процесс javascript. Это состоит из некоторых вызовов API и длительных циклов. Моя проблема в том, что я не могу заставить код ждать пока все счетчики не появятся перед запуском javascript. Я пробовал setTimeout и requestAnimationFrame, как предлагают несколько других постов, но скрипт все равно запускается, и спиннеры появляются с задержкой.

HTML Фрагмент, сгенерированный материализацией:

<div class="select-wrapper">
<input class="select-dropdown dropdown-trigger" type="text" readonly="true" data-target="select-options-262e9372-9f06-8033-4ddc-5ed565152b96">
<ul id="select-options-262e9372-9f06-8033-4ddc-5ed565152b96" class="dropdown-content select-dropdown" tabindex="0" style="">
<li class="disabled" id="select-options-262e9372-9f06-8033-4ddc-5ed565152b960" tabindex="0"><span>All Competitors</span></li>
<li id="select-options-262e9372-9f06-8033-4ddc-5ed565152b961" tabindex="0" class=""><span>Comp A</span></li>
<li id="select-options-262e9372-9f06-8033-4ddc-5ed565152b962" tabindex="0" class="selected"><span>Comp B</span></li>
<li id="select-options-262e9372-9f06-8033-4ddc-5ed565152b963" tabindex="0"><span>Comp C</span></li>
</ul>
<svg class="caret" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5 5 5-5z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg>
<select id="competitor" tabindex="-1">
<option value="" disabled="">All Competitors</option>
<option value="a" selected="">Comp A</option>
<option value="b">Comp B</option>
<option value="c">Comp C</option>
</select>
</div>

Функция счетчика:

function showLoadingSpinners() {
    $("#filtersSpinner").addClass("show");
    $("#mapSpinner").addClass("show");
    $("#tableSpinner").addClass("show");
    $("#submitButton").prop("disabled", true);
    if (listOfStuff.length >= maxStoresForPricing) {
        $("#tooManyMessage").fadeIn();
    }
}

Попытка A:

$("#competitor").on("change", function () {
    showLoadingSpinners();
    secondStep();

    function secondStep() {
        if (!$("#filtersSpinner").hasClass("show")) {
            window.requestAnimationFrame(secondStep);
        } else {
            doLotsOfStuff();
        }
    }
});

Попытка B:

$("#competitor").on("change", function () {
    showLoadingSpinners();
    setTimeout(function () {
       doLotsOfStuff();
    }, 350);
});

1 Ответ

1 голос
/ 01 мая 2020

Я бы предложил поработать с Javascript Promise над тем, что вы хотите сделать, а если быть более точным, было бы действительно неплохо поработать с Promise.all().

* 1006. * РЕДАКТИРОВАТЬ Небольшой пример для проверки в приведенном ниже фрагменте.
const spinnerA = new Promise((resolve, reject) => {
  setTimeout(() =>{
    document.getElementById("textA").style.display = "block";
    resolve(true);
  },3000);
});
const spinnerB = new Promise((resolve, reject) => {
  setTimeout(() =>{
    document.getElementById("textB").style.display = "block";
    resolve(true);
  },3000);
});

Promise.all([spinnerA, spinnerB]).then(() => { 
  alert(document.getElementById("last").textContent);
});
#textA {
  display: none;
}
#textB {
  display: none;
}
#last {
  display: none;
}
<div id="textA">text A</div>
<div id="textB">text B</div>
<div id="last">both text are in a visible state and you will see them once you close this alertbox </div>
...