Synchronous / asynchronous nature of browser rendering and javascript execution

I have a processing that takes a few seconds, so I want to add a visual indicator during its execution.

.processing { background-color: #ff0000; } <div id="mydiv"> Processing </div> 

Script:

 $("#mydiv").addClass("processing"); // Do some long running processing $("#mydiv").removeClass("processing"); 

I naively thought that the class would be applied to the div and the user interface would be updated. However, by running this in a browser (at least in Firefox), the div never stands out. Can someone explain to me why my my div is never highlighted? The class is added, processing is performed, and then the class is deleted; the user interface is not updated between them, and the user never sees a red background.

I know that JS is single-threaded, but I always assumed that browser rendering would be done synchronously when and when the DOM is updated. Is my assumption wrong?

And more importantly, what is the recommended way to achieve this effect? Should I use setTimeout to make slow processing asynchronous and work with a callback? There should be a better way, since I really don't need asynchronous behavior here; I just want the user interface updated.

EDIT:

JSFiddle: http://jsfiddle.net/SE8wD/5/

(Note: you may need to adjust the number of iterations of the loop to give you a reasonable delay on your PC)

+6
source share
4 answers

I do not recommend freezing the browser for a weight script. In this case, I prefer to change the code to not freeze the browser and DOM. If there is a loop in your code, you can call the function with a delay (using setInterval) and save some status variable somewhere. For instance:

 for(var i=0; i<1000000; i++) { // do something } 

May be:

 var i = 0; var intervalID; var _f = function() { // do something i++; if(i==1000000) clearInterval(intervalID); } intervalID = setInterval(_f,1); 

Or something similar and more optimized. Your code will be a little more complicated and slower ... but you can prevent browser freezing and you can create an extended preload status bar.

+1
source

You should probably do the processing in a separate event, for example:

 $("#mydiv").addClass("processing"); setTimeout(function(){ // This runs as a seperate event after // Do some long running processing $("#mydiv").removeClass("processing"); },1); 

Thus, the browser should redraw the screen using processing , while the long step will start as a separate event and delete the processing message when it is done.

+1
source

Make a redraw . Use Soren code as an alternative, because processing in the UI thread sounds bad ...

0
source

The browser is completely free when to repaint and when to melt. Different engines will show different behavior. For further reading, see When does DOM overflow occur? . In your example, the browser sees that you add the class and delete it right after that, so it may not do anything.

To avoid this, you can use a hacked file with a forced break or do asynchronous calculation using WebWorkers or setTimeout or something like that.

0
source

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


All Articles