Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do something before and after blocking code

Forgive my bad title, but right now, I don't even know what I don't know.

If I have an HTML page that looks something like this:

<html>
    <head>
        <script>
            jQuery(document).ready(function(){
                jQuery("#modalDiv").show();
                //This part takes up to a few seconds to execute and blocks the browser
                for(var i = 0; i < 10000; i++){
                    console.log("doing something");
                }
                jQuery("#modalDiv").hide();
            });
        </script>
        <style>
            #modalDiv{
                background-color:red;
                height:100px;
                width:100px;
            }
        </style>
    </head>
    <body>
        <div id="modalDiv"></div>
    </body>
</html>

The element with the ID "modalDiv" is never displayed on the page. I'm not trying to solve this "problem," I'm just trying to understand what is going on under the hood causing my script to behave as it does.

like image 603
user2569432 Avatar asked Jun 13 '26 15:06

user2569432


2 Answers

The browser doesn't render changes to the DOM until all synchronous actions have completed, and your code returns control to the main event loop. This allows you to make lots of changes to the page without the user seeing all the intermediate forms -- it waits until you're done and just shows the final result.

One way to force immediate update is to use animations.

$(function () {
    jQuery("#modalDiv").show(5000);
    //This part takes up to a few seconds to execute and blocks the browser
    for (var i = 0; i < 10000; i++) {
        console.log("doing something");
    }
    jQuery("#modalDiv").hide(5000);
});

DEMO

like image 173
Barmar Avatar answered Jun 15 '26 06:06

Barmar


Some browsers wait until a thread of javascript finishes executing before they update the screen with changes made to the DOM. If there are multiple changes to the DOM being made in the javascript, this is the more performant way of doing things because it lays things out once and only displays things on the screen once. The details of this behavior will/can vary between browsers as it is a performance optimization and they all end up with the same end result once the JS is done executing.

There are tricks for force the browser to update the screen by requesting DOM properties that require the layout to be current. You can read this article on how to trigger a reflow/repaint: http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/ and another relevant article: http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html.

For example, you should able to force a reflow with this (adding the call to .offset()):

jQuery("#modalDiv").show().offset();
//This part takes up to a few seconds to execute and blocks the browser
for(var i = 0; i < 10000; i++){
    console.log("doing something");
}
jQuery("#modalDiv").hide();

The other thing one can do to let the screen update is to run part of your code on a setTimeout() because this lets the first part of your javascript actually finish executing (and thus the screen will be updated). This doesn't actually run everything synchronously as in your code example, but is sometimes an OK workaround.

like image 38
jfriend00 Avatar answered Jun 15 '26 06:06

jfriend00



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!