jQuery/Javascript - How to wait for manipulated DOM to update before proceeding with function

后端 未结 4 663
[愿得一人]
[愿得一人] 2020-11-30 07:16

What I\'m trying to do is to update a simple div to say \"Processing...\" before executing a CPU-intensive script (it takes 3-12 seconds to run, no AJAX) then update the div

相关标签:
4条回答
  • 2020-11-30 07:49

    As of 2019 one uses double requesAnimationFrame to skip a frame instead of creating a race condition using setTimeout.

    ....
    function doRun() {
        document.getElementById('msg').innerHTML = 'Processing JS...';
        requestAnimationFrame(() =>
        requestAnimationFrame(function(){
             start = new Date();
             end = addSecs(start,5);
             do {start = new Date();} while (end-start > 0);
             document.getElementById('msg').innerHTML = 'Finished Processing';   
        }))
    }
    ...
    
    0 讨论(0)
  • 2020-11-30 07:54

    I had to wait for jQuery to manipulate the DOM and then grap the changes (load form fields multiple times into a form, then to submit it). The DOM grew and the insertion took longer and longer. I saved the changes using ajax to have to user to be able to continue where he left off.

    This did NOT WORK as intended:

    jQuery('.parentEl').prepend('<p>newContent</p>');
    doSave(); // wrapping it into timeout was to short as well sometimes
    

    Since jQuery functions like .prepend() do continue the chain only when done, the following seemed to do the trick:

    jQuery('.parentEl').prepend('<p>newContent</p>').queue(function() {
      doSave();
    });
    
    0 讨论(0)
  • 2020-11-30 08:07

    You have a loop that runs for 5 seconds and freezes the web browser during that time. Since the web browser is frozen it can't do any rendering. You should be using setTimeout() instead of a loop, but I'm assuming that loop is just a replacement for a CPU intensive function that takes a while? You can use setTimeout to give the browser a chance to render before executing your function:

    jQuery:

    $(function() {
        $('button').click(function(){
            (function(cont){
                $('div').text('Processing JQ...');  
                start = new Date();
                end = addSecs(start,5);
                setTimeout(cont, 1);
            })(function(){
                do {start = new Date();} while (end-start > 0);
                $('div').text('Finished JQ');   
            })
        });
    });
    

    Vanilla JS:

    document.getElementsByTagName('a')[0].onclick = function(){
        doRun(function(){
             do {start = new Date();} while (end-start > 0);
             document.getElementById('msg').innerHTML = 'Finished JS';   
        });
        return false;
    };
    
    function doRun(cont){
        document.getElementById('msg').innerHTML = 'Processing JS...';
        start = new Date();
        end = addSecs(start,5);
        setTimeout(cont, 1);
    }
    

    You should also remember to always declare all variables using the var keyword, and avoid exposing them to the global scope. Here is a JSFiddle:

    http://jsfiddle.net/Paulpro/ypQ6m/

    0 讨论(0)
  • 2020-11-30 08:09

    set it to processing, then do a setTimeout to prevent the cpu intensive task from running until after the div has been updated.

    <!DOCTYPE html>
    <html>
    <head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" ></script>
    <script>
    function addSecs(d, s) {return new Date(d.valueOf()+s*1000);}
    function doRun() {
        document.getElementById('msg').innerHTML = 'Processing JS...';
        setTimeout(function(){
             start = new Date();
             end = addSecs(start,5);
             do {start = new Date();} while (end-start > 0);
             document.getElementById('msg').innerHTML = 'Finished Processing';   
        },10);
    }
    $(function() {
        $('button').click(doRun);
    });    
    </script>
        </head>
    <body>
        <div id="msg">Not Started</div>
        <button>jQuery</button>
        <a href="#" onclick="doRun()">javascript</a>
    </body>
    </html>
    

    you can modify the setTimeout delay as needed, it may need to be larger for slower machines/browsers.

    Edit:

    You could also use an alert or a confirm dialog to allow the page time to update.

    document.getElementById('msg').innerHTML = 'Processing JS...';
    if ( confirm( "This task may take several seconds. Do you wish to continue?" ) ) {
         // run code here
    }
    
    0 讨论(0)
提交回复
热议问题