Skip to content Skip to sidebar Skip to footer

No Page Rendering While Img Onload-event In Javascript

I have got a vanilla Javascript that sets an img's src attribute to a data-uri. In the function assigned to the onload event, I try to show the progress of some preparations on the

Solution 1:

Unless you go with background Web Workers massaging (more complicated, espacially in your situation), the rendering of your progress bar can only occur after a complete return from your script; therefore, after each showProgress call. Now, how to return, render then restart for the remaining? Well, that's where a setTimeout of 0 millisecond comes handy. With it, the following should work:

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

An alternative approach to nesting code would be a kind of recursive call - yet each call will complete before the following will start - on an array of steps, like this:

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 emptyfunctiondisplayAfterEachStep() {
    steps.shift()(); // Pull out the first step and run itif(steps.length > 0) // if there's still stepssetTimeout(displayAfterEachStep, 0); // Recall the process after page rendering
}
img.onload = displayAfterEachStep;

Many other good ideas to get around that lack of Rendered Event in HTML can be found here and around.

Solution 2:

I came back to the matter after working on some other projects and solved my problem using Promises like this:

showProgress("Loading image...", 0.0) // Reset progress barconst img = document.createElement("img") // Get image elementconst promise = newPromise((resolve, reject) => { // Instantiate a Promise
  img.onload = resolve // Set onload callback to resolve (this triggers the chain)
  img.onerror = reject

  img.src = "/path/to/image.jpg"// Set src attribute to start loading image
})
.then(() => { // When promise is resolved: Start step 2showProgress("Preparing image...", 0.3)
  // ...
})
.then(() => { // When promise is resolved: Start step 3showProgress("Preparing tools...", 0.6)
  // ...
})
.then(() => { // When promise is resolved: Finish upshowProgress("Ready...", 1)
  // ...
})

With Promises you can put asynchronous tasks in an order while still maintaining readability.

Further reading: Promises on MDN

Post a Comment for "No Page Rendering While Img Onload-event In Javascript"