DOM update followed by a large loop does not display in time

Part of my page has ~ 9000 elements in it, and it needs to be rebuilt often, which can take several seconds.

So, I made a small overlay widget that covers the element using Loading.. message. Right before I rebuild the item, I call showOverlay() , and after the loop, I call hideOverlay() .

But the loop blocks the page before my Loading... message appears, and therefore it never appears.

 function rebuild() { showOverlay(); // The overlay never appears... for (var i=0;i<9000;i++) { // append element... } hideOverlay(); } 

How can I wait for the overlay to be displayed BEFORE I start the loop?

+4
source share
4 answers
 function do_rebuild() { for (var i=0;i<9000;i++) { // append element... } hideOverlay(); } function rebuild() { showOverlay(); // The overlay will appear window.setTimeout('do_rebuild();',1); } 

I know only one browser.

+3
source

You need to put your loop in the given timeout so that it does not delay the page. Even if your overlay is displayed, no one likes their page freeze

 var counter = 0; function rebuild() { showOverlay(); doWork(); } function doWork() { if(counter < 9000){ // append element counter++; setTimeout(function(){ doWork(); },10); } else { hideOverlay(); } } 

EDIT . This answer will actually take significantly longer to process the page. Somewhere in the region of 90 seconds, which is quite unacceptable, another alternative could be setting a timeout every 100 iterations, which will add about 1 second to the total load time, but should stop the page freezing.

 function doWork() { if(counter < 9000){ // append element if(counter % 100 == 0) { setTimeout(function(){ doWork(); },10); counter++; } else { doWork(); counter++; } } else { hideOverlay(); } } 
+1
source

Other answers show how to do this using a pseudo-stream using timers.

In the meantime, I found out about web workers , which are a streaming solution that separates script execution from DOM updates.

They are currently supported in WebKit and Firefox, and support for IE 10 is planned.

0
source

you can try the following:

 var loopCount = 0, build = function() { var frgm = document.createDocumentFragment(); for (var i = 0; i < 200 && loopCount < 9000; i++) { // some codes frgm.appendChild(someElement); loopCount ++; } parentNode.appendChild(frgm); if (loopCount < 9000) { setTimeout(build, 10); } }; function rebuild() { showOverlay(); // The overlay never appears... build(); hideOverlay(); } 
0
source

Source: https://habr.com/ru/post/1398907/


All Articles