admin管理员组

文章数量:1306138

I had a task to make a progress bar and a process duration timer along with it. So, not thinking twice I did this:

<div class="mainInfo">
    <div id="timer"><span id="elapsedText">0:00</span>/<span id="durationText">3:00</span></div>
    <div id="progressBar"><div id="progress" style="width:0;"></div></div>
</div>​

And the JS:

var time = 1000;
var duration = 180;

var $progress = $("#progress");
var $elapsedText = $("#elapsedText");

updateTime();

function updateTime() {
    var elapsed = time / 1000;
    $elapsedText.text(Math.floor(elapsed / 60) + ":" + Math.floor(elapsed % 60));
    $progress.css('width', (elapsed * 100 / duration) + "%");
    time = time + 1000;
    setTimeout("updateTime()", 1000);
}​

Time is actually retrieved from another variable - this ones for the demo (to illustrate that I actually have the value in miliseconds).

And it worked (not only on my PC), and still does, but the procmon shows a CPU spike on browser (chrome, ff) process when this cycle is running - 30-40% instead of regular 0,5%.

Is there a more efficient way to do this?

I had a task to make a progress bar and a process duration timer along with it. So, not thinking twice I did this:

<div class="mainInfo">
    <div id="timer"><span id="elapsedText">0:00</span>/<span id="durationText">3:00</span></div>
    <div id="progressBar"><div id="progress" style="width:0;"></div></div>
</div>​

And the JS:

var time = 1000;
var duration = 180;

var $progress = $("#progress");
var $elapsedText = $("#elapsedText");

updateTime();

function updateTime() {
    var elapsed = time / 1000;
    $elapsedText.text(Math.floor(elapsed / 60) + ":" + Math.floor(elapsed % 60));
    $progress.css('width', (elapsed * 100 / duration) + "%");
    time = time + 1000;
    setTimeout("updateTime()", 1000);
}​

Time is actually retrieved from another variable - this ones for the demo (to illustrate that I actually have the value in miliseconds).

And it worked (not only on my PC), and still does, but the procmon shows a CPU spike on browser (chrome, ff) process when this cycle is running - 30-40% instead of regular 0,5%.

Is there a more efficient way to do this?

Share Improve this question asked Dec 12, 2012 at 21:33 povilasppovilasp 2,3961 gold badge23 silver badges36 bronze badges 4
  • 2 "updateTime()" => updateTime – John Dvorak Commented Dec 12, 2012 at 21:35
  • Use setTimeout(updateTime, 1000);, do never pass a string to setTimeout! – Bergi Commented Dec 12, 2012 at 21:39
  • That was a stupid mistake, that I see, though I wouldn't say "never pass a string to setTimeout" since it could be used not only for one function call :) – povilasp Commented Dec 12, 2012 at 21:45
  • @povilasp anonymous functions are always faster than running a piler. Only ever pass a string if you feel eval would be the other option. That is, never. – John Dvorak Commented Dec 12, 2012 at 21:50
Add a ment  | 

5 Answers 5

Reset to default 4

There is a standard function for that: SetInterval(function, delay_in_ms).

It calls a function in millisecond intervals.

Instead of

setTimeout("updateTime()", 1000);

use

setTimeout(updateTime, 1000);

The fact that you're invoking the piler each second could really hurt performance. Passing a string to setTimeout is basically causing an eval within the setTimeout.

There is a default for that, and that is setInterval.

Be careful, the function passed as the first argument to setInterval is always executed in global scope.

Number two, a progress bar is usually created along-side expensive processes. You are using it for display purposes only and forcing a delay, which I don't particularly find useful, but if you like the layout, I guess you can go for it.

The way you would usually use it is:

executeFirstPotentiallyExpensiveProcess();// this is a call to a big function.
// then update the value of the progress bar in percentage style.
executeSecondPotentiallyExpensiveFunction()// this is the second part of your process.
// then again update..
// repeat until you have 100%.
// Basically, you logically divide the expenses of your various executions
// into numerable bits, preferably equal to one another for your convenience,
// but you chunk your loading process or whatever type of process and increment
// the progress after each chunk is plete.

Your use of jQuery disturbs me...

var time = 1000;
var duration = 180;

var $progress = document.getElementById("progress");
var $elapsedText = document.getElementById("elapsedText");

var beginTimestamp = new Date().getTime();

updateTime();
setInterval(updateTime,1000);

function updateTime() {
    var now = new Date().getTime();
    var elapsed = now-beginTimeStamp + time;
    $elapsedText.firstChild.nodeValue = Math.floor(elapsed / 60) + ":" + Math.floor(elapsed % 60);
    $progress.style.width = (elapsed * 100 / duration) + "%";
}​

Maybe without jQuery your browser might run better ;)

Try with the function setInterval.

本文标签: Efficient ways to do a timer which updates every second in JavaScriptStack Overflow