javascript - 加载微调器 div 未及时渲染

标签 javascript html css

TL;博士:

  • loadingSpinner div 在昂贵的代码之前打开,在昂贵的代码之后关闭
  • 两者showLoading()hideLoading()调用log()它将一条消息写入 console.log()和一个元素的 innerHTML
  • loadingSpinner在昂贵的代码完成之前,DOM 中的日志消息不会显示,但 console.log()消息在应该出现的时候出现

我有一个对存储在 loadingSpinner 中的 div 的引用这只是一个位于所有其他内容之上的框,应该表明该网站正在做一些工作。我使用这些函数来切换所述 div 的可见性( .hidden 在我的 CSS 中只是 display: none; )

function hideLoading() {
    log('hiding')
    loadingSpinner.style.display = 'none'
    //setTimeout(function (){loadingSpinner.style.display = 'none'}, 10)
    //window.getComputedStyle(loadingSpinner) // <-- TRIED FORCING REDRAW
    //if (!loadingSpinner.classList.contains('hidden')) {
        //loadingSpinner.classList.add('hidden')
    //}
}

function showLoading(text) {
    log('Showing')
    loadingSpinner.innerHTML = text
    loadingSpinner.style.display = 'block'
    //setTimeout(function (){loadingSpinner.style.display = 'block'}, 10)
    //window.getComputedStyle(loadingSpinner)
    //if (loadingSpinner.classList.contains('hidden')) {
        //loadingSpinner.classList.remove('hidden')
    //}
}

function log(s) {
    console.log(s)
    logDisplay.innerText = s
}

注释掉的代码是我已经尝试过的不同的东西。显示和隐藏功能本身工作正常。我可以看出,由于调用了log(),所以在正确的时间调用了隐藏和显示函数。 .

据我所知,我有几个实例,网站在客户端上执行一些昂贵/长时间运行的任务,其中任何内容都不应该是异步的(不确定 Array.prototype.forEach() )。问题是loadingSpinner仅在昂贵的任务完成后才显示 hideLoading()立即隐藏它。我确实通过添加 setTimeout() 确认了这一点至hideLoading() .

function updateDOM() {
    showLoading('Updating DOM...') // <--- SHOW

    log('Updating DOM') // <--- OTHER LOG MESSAGE

    codeContainer.innerHTML = '' // <--- start of long running task
    codes.forEach(code => {
        if (code.base64 === '') {
            backgroundQr.set({value: code.data})
            code.base64 = backgroundQr.toDataURL()
        }
        addCodeElement(codeContainer, code)
    });
    if (codes.length === 0) {
        editingId = -1
    } // <--- end of long running task

    hideLoading() // <--- HIDE
}

控制台日志顺序正确:

Showing
Updating DOM
hiding

log() 的文字都没有写入logDisplay -元素也不是loadingSpinner本身在应该出现的时候出现,所以我认为这是一个渲染问题?

这个问题在多个地方都是一致的,而不仅仅是 updateDOM()功能。

最佳答案

由于昂贵的代码是同步执行的,浏览器太忙于运行它,没有时间将内容渲染到 DOM。您可以采取的一种方法是使用 promises 异步执行昂贵的代码。和 setTimeout函数来延迟昂贵的执行或将其发送到执行队列的末尾。

我创建了下面的代码片段来展示该方法,您需要:

  • 微调器处理函数
  • 昂贵的执行器函数
  • 异步代码运行器
  • 将它们组合在一起的主要脚本

下面的代码片段包含两个示例,您可以在两个示例之间切换,一个通过运行 main(); 执行成功,另一个通过运行 main(true) 执行失败;.

function showSpinner() {
    document.querySelector('#spinner').style.display = 'block';
}
function hideSpinner() {
    document.querySelector('#spinner').style.display = 'none';
}
function executeSuccess() { // runs something expensive that succeeds
    return 'data';
}
function executeFailure() { // runs something expensive that fails
    throw 'issue';
}
function promiseToRunAsync(executor, ...params) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            try { resolve(executor(...params)); }
            catch (error) { reject(error); }
        }, 1000); // arbitrary time that you can set to anything including 0
    });
}
function main(failure = false) {
    showSpinner(); // show spinner
    promiseToRunAsync(failure ? executeFailure : executeSuccess) // execute anync
    .then((results) => {
        console.log('yay', results);
        document.querySelector('#content').innerHTML = results;
        hideSpinner(); // hide spinner in case of success
    })
    .catch((error) => {
        console.log('oops', error);
        hideSpinner(); // hide spinner in case of failure
    });
    // ATTN code here will run before the spinner is hidden
}
main(); // executes the success scenario
// main(true); // executes the failure scenario
#spinner {
  display: none;
}
<div id="spinner">Spinning...</div>
<div id="content"></div>

注意:在此处的示例中,我在执行中添加了 1 秒的延迟,只是为了说明发生的情况,但您可能需要设置自己的等待时间或不等待时间完全没有。

关于javascript - 加载微调器 div 未及时渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62190222/

相关文章:

CSS显示一个恒定的背景来掩盖

html - 尝试几种常见解决方案后图像未水平对齐

javascript - Sweet Alert Confirm - 获取用户响应

javascript - parseFloat 函数没有按预期工作

html - 键盘不会在 iPhone 搜索时关闭

html - Div 不考虑高度百分比

html - 我应该在实际元素开发中使用基础吗?

javascript - HTML - 如何仅在激活省略号时显示工具提示

javascript - 如何从 getItemMetadata 返回变量?

javascript - rails : Include External JavaScript