Javascript 中的 img onload-event 时没有页面渲染

问题描述

我有一个普通的 Javascript,可以将 img 的 src 属性设置为 data-uri。 在分配给 onload 事件的函数中,我尝试在页面显示一些可能需要一段时间的准备工作的进度(生成了多个画布元素并设置了一些设置)。

这是应该呈现进度条的函数

let progress = document.querySelector('.progress');

function showProgress(message,percent) {
    console.log(message + ' (' + (percent * 100).toFixed(0) + '%)');
    progress.querySelector('.progress--message').innerHTML = message;
    progress.querySelector('.progress--bar-container--bar').style.width = (percent * 100).toFixed(0) + '%';
}

代码是这样运行的:

img.onload = function() {
    showProgress('Preparing image...' .1);

    // Some preparations...

    showProgress('Preparing tools...',.2);

    // etc...

    showProgress('Done...',1);
}

控制台日志按预期工作,但 DOM 元素的渲染会停止,直到函数结束,并在一切准备就绪后显示“完成”状态。

onload 事件处理中是否存在任何渲染阻塞,是否可以绕过?或者我错过了什么?代码本身对结果没有任何影响。甚至函数中的第一行也有这种奇怪的行为。

解决方法

除非您使用后台 Web Workers 按摩(更复杂,尤其是在您的情况下),渲染进度条只能在从您的服务器完全返回后发生。脚本;因此,在每次 showProgress 调用之后。现在,如何返回,渲染然后重新启动剩余的?嗯,这就是 0 毫秒的 setTimeout 派上用场的地方。有了它,以下应该可以工作:

img.onload = function() {
    showProgress('Preparing image...' .1);
    setTimeout(function() {
        // Some preparations...
        showProgress('Preparing tools...',.2);
        setTimeout(function() {
            // etc...
            showProgress('Done...',1);
        },0);
    },0);
}

嵌套代码的另一种方法是一种递归调用 - 但每次调用都会在以下开始之前完成 - 在一系列步骤上,如下所示:

steps = [
  function() { // first step (img loading just completed so,show Preparing it right away)
      showProgress('Preparing image...',.1);
  },function() { // second step
      // Some preparations...
      showProgress('Preparing tools...',.2);
  },// other steps...
  function() { // last step
      // Last things to do...
      showProgress('Done...',1);
  }
];
// function that processes "steps" - array of at least 1 function - until empty
function displayAfterEachStep() {
    steps.shift()(); // Pull out the first step and run it
    if(steps.length > 0) // if there's still steps
         setTimeout(displayAfterEachStep,0); // Recall the process after page rendering
}
img.onload = displayAfterEachStep;

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...