1

I have to show a progressbar/status indicator using pure JavaScript, no jQuery please.
My code is:

<script type="text/javascript">
function processObjects()
{
    var selectedRows = {}; // array of selected rows from table
    var count = selectedRows.length; // count value exceeds 100
    var myDiv = document.getElementById("myDiv");
    for(var i=0; i < count; i++)
    {
        myDiv.innerHTML = (i+1)+"/"+count;
        // Process each object from array
        // no Ajax call
        // takes almost 0.1 sec for each object <- this is not an issue
    }
}
</script>

<div id="myDiv"></div>
<input type="button" onclick="processObjects()" value="Process Objects" />
<table>
    <!-- Table with lots of rows with checkboxs -->
</table>

Problem:

When I run this script in any Browser, the page becomes unresponsive and does not update the status in using innerHTML as 1/100...2/100...3/100 as so on.

what could be the possible solution to stop browser from becoming unresponsive?

3
  • 1
    You can try use WebWorkers -developer.mozilla.org/ru/docs/DOM/Using_web_workers Commented Oct 28, 2015 at 13:59
  • 3
    Or batch it in chunks via setTimeout() allowing the dom to update between calls. Commented Oct 28, 2015 at 14:01
  • i see in your code that your opening script doesn't have a closing quotation Commented Oct 28, 2015 at 14:02

2 Answers 2

3

JS is single threaded and it has to take the full attention of the browser while being inside a function.

You need to call long processes through setTimeout() function if you need to give the browser a chance to breath while processing something long.

See how I do this in the following example:

function doProgress(count) {

    if (count == 100)
       return;

    document.getElementById("myDiv").innerHTML = count;
    count++;

    setTimeout(doProgress, 0, count);   //<- calling the same function with new count here. "0" is the milliseconds to call it after. "count" is the argument to pass

}

It only demonstrate this technique and there are lot of best practices to follow once you master it.

Sign up to request clarification or add additional context in comments.

1 Comment

good one Charlie, so the problem was with using a for loop...much helpful..:)
1

Javascript locks the view while code is executing (unless you are using a canvas) so you must end the execution of your code before being able to see results in your DOM.
Even if this article is about angular, the intro explains quite well how javascript works and why it freezes a browser http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

if you want to keep it simple you can do this:

<script type="text/javascript">
    var start=0;
    var selectedRows = {}; // array of selected rows from table
    var count = selectedRows.length; // count value exceeds 100 value
    var myDiv = document.getElementById("myDiv");

function processObject(){
    myDiv.innerHTML = (++start)+"/"+count;
    // Process one object from array using "start" as index
    if(start<count){
        setTimeout(processObject, 100);
    }
}
function processObjects(){
    //eventually update values
    selectedRows=[] //adds items to array
    count = selectedRows.length;
    myDiv = document.getElementById("myDiv");
    processObject();
}
</script>

<div id="myDiv"></div>
<input type="button" onclick="processObjects()" value="Process Objects" />
<table>
    <!-- Table with lots of rows with checkboxs -->
</table>

if you don't want to use global variables you can do this:

function processObject(){
    processObject.myDiv.innerHTML = (++processObject.start)+"/"+processObject.count;
    // Process one object from array using "start" as index
    if(processObject.start<processObject.count){
        setTimeout(processObject, 100);
    }
}
function processObjects(){
    processObject.selectedRows=[]; //array with rows to process 
    processObject.count=processObject.selectedRows.length
    processObject.start=0;
    processObject.myDiv=document.getElementById("myDiv");
    processObject();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.