How do I report the progress of a JavaScript function?

I have a JavaScript function that is quite long and performs a number of tasks, I would like to report the progress to the user by updating the contents of the SPAN element with a message when I go. I tried adding document.getElementById ('spnProgress'). InnerText = ... statements in all functional code.

However, while the function executes the user interface, it will not be updated, so you will always see the last message recorded in the SPAN, which is not very useful.

My current solution is to break the task down into several functions, at the end of each of them I set the SPAN message and then “run” the next one with window.setTimeout with a very short delay (say 10 ms). This gives control and allows the browser to redraw the SPAN with the updated message before starting the next step.

However, I find it very dirty and hard to follow the code, I think there should be a better way. Anyone have any suggestions? Is there a way to force the SPAN to redraw without leaving the function context?

thanks

+7
javascript repaint progress
source share
6 answers

The way you do this is the right way (for the time being, this may change as standards become available and adopted [see Andrew Aylett answer ], but not yet). You must ensure that the browser can update its user interfaces. I found that the more I think so, the cleaner it all turns out, but my first few hits were really “dirty”. I hope you find the same thing that you are used to.

+7
source share

If you have control over the target browser, you can use the HTML5 workflow to do the work in the background.

+3
source share

You need to know that in some browsers you will receive a script timeout message if you have a long script. Therefore, it is actually advisable to split this with a timer.

Having said that, if you are looking for a really structured way to do this, you can look at the background task library that I wrote for the spell checker project. This allows you to implement a map / reduce the number of timer datasets.

https://github.com/jameswestgate/taskjs

+2
source share

This is similar to the question of whether it is possible to interrupt a procedure without interrupting a procedure. The answer is no. You should use setTimeout () or setInterval () to transfer control to the browser rendering engine.

If you use setInterval (), you can get this process, and in your executing function, just update the external variable that will be polled by the function called setInterval (). Thus, you should only make one call, and not do it in a loop.

0
source share

Not that I knew. You can break up your code so that individual functions can share variables in this way:

var a = some_local_state(); runTasksWithProgress([ function() { do_some_work(a); a = a + 1; }, function() { do_some_other_work(a); a = a * 2; }, ... ]); 

runTasksWithProgress is a bit trickier. You basically call the first task, update the status, and then set up a callback to perform subsequent tasks.

This approach can relieve some of the pain.

0
source share

Something like this might work if your function runs in a loop. It checks the amount of time elapsed and updates the progress bar if 1/2 second has passed. (The example is not verified, so you may need to play a little with it.)

 var start; function longRunning(lastState){ start = (new Date); for(var i = lastState; i < 1e6 /*= 1000000 iterations */; ++i){ if((new Date)-start<500){ // do your stuff; } else{ // call a function to update the progress bar updateProgressBar(); // continue the loop... setTimeout(function(){longRunning(i);},13); break; } } } longRunning(0); 
0
source share

All Articles