Suppose you have 3 arrays you want to loop over, with lengths x, y, and z, and for each loop, you want to update a progress bar. For example:
function run() {
x = 100;
y = 100;
z = 10;
count = 0;
for (i=0; i<x; i++) {
//some code
for (j=0; j<y; j++) {
// some code
for (k=0; k<z; k++) {
//some code
$("#progressbar").reportprogress(100*++count/(x*y*z));
}
}
}
}
However, in this example, the progress bar doesn't update until the function completes. Therefore, I believe I need to use setTimeout to make the progress bar update while the function runs, although I'm not sure how to do that when you have nested for loops.
Do I need to break each loop up into its own function, or can I leave them as nested for loops?
I created a jsfiddle page in case you'd like to run the current function: http://jsfiddle.net/jrenfree/6V4Xp/
Thanks!
TL;DR: Use CPS: http://jsfiddle.net/christophercurrie/DHqeR/
The problem with the code in the accepted answer (as of Jun 26 '12) is that it creates a queue of timeout events that don't fire until the triple loop has already exited. You're not actually seeing the progress bar update in real-time, but seeing a late report of what the values of the variables were at the time they were captured in the inner closure.
I'd expect that your 'recursive' solution looks a bit like using continuation-passing style to ensure that your loop doesn't continue until after you've yielded control via setTimeout. You might not know you were using CPS, but if you're using setTimeout to implement a loop, you're probably pretty close to it.
I've spelled out this approach for future reference, because it's useful to know, and the resulting demo performs better than the ones presented. With triple nested loops it looks a bit convoluted, so it may be overkill for your use case, but can be useful in other applications.
You can see on jsFiddle that this version updates quite smoothly.
If you want to use setTimeout you could capture the x, y, z and count variables into a closure:
Live demo.
I've found a solution based on the last reply but changing the interval time to one. This solution show a loader while the main thread is doing an intensive task.
Define this function:
And call it like this:
Probably a jquery function in reportprogress plugin uses a setTimeout. For example if you use setTimeout and make it run after 0 milliseconds it doesn't mean that this will be run immediately. The script will be executed when no other javascript is executed.
Here you can see that i try to log count when its equal to 0. If i do it in setTimeout callback function then that is executed after all cycles and you will get 100000 no 0. This explains why progress-bar shows only 100%. js Fiddle link to this script
wrapping everything after for(i) in setTimeout callback function made the progress-bar work. js Fiddle link
Edit: Just checked that style setting code for item is actually executed all the time. I think that it might be a browser priority to execute javascript first and then display CSS changes.
I wrote a another example where i replaced first for loop with a setInterval function. It's a bit wrong to use it like this but maybe you can solve this with this hack.
JS Fiddle