2

This js will take a value, subtract X amount from it, and then count up to that value.

I attempted to accomplish this task by doing a simple while loop, but I couldn't get it work.

I was wondering if anyone could comment on how or why the while loop method below doesn't work.

This is the only way I could get it to work:

function _initCountUpUsers()
{
    var totalUsers = $('#totalUsers');
    var ceiling = parseInt(totalUsers.html());
    var floor = ceiling - 10;

    function updateTotalUsers()
    {
        if(floor < ceiling)
        {
            totalUsers.html(floor);
            floor++;
        }
    }

    window.setInterval(updateTotalUsers, 1000, floor);
}

Non-working While method:

function _initCountUpUsers()
{
    var totalUsers = $('#totalUsers');
    var ceiling = parseInt(totalUsers.html());
    var floor = ceiling - 10;

    function updateTotalUsers()
    {
        totalUsers.html(floor);
        floor++;
    }

    while(floor < ceiling)
    {
         window.setInterval(updateTotalUsers, 1000, floor);       
    }

}
2
  • The reason why I wanted to explore the while (or even a for) loop method was that I thought it would be the better practice or more academic method of doing things. Commented Aug 2, 2010 at 18:30
  • It would be cleaner, but it's not really workable. Fortunately, JavaScript is pretty flexible - you can probably come up with something that'll look closer to what you want (see my updated answer). Commented Aug 2, 2010 at 18:39

2 Answers 2

3

I'm not sure why you didn't want to stick with your first method, but...

while(floor < ceiling)
{
     window.setInterval(updateTotalUsers, 1000, floor);       
}

This is going to start 10 separate timers, each set to fire once a second, each set to increment floor and update totalUsers, and none of them ever terminating. If they were to fire, you'd see the count increase by ten each second, vs. by one in your first example. However, none of them will actually fire, since you'll loop forever waiting for floor to reach ceiling!

JavaScript is single-threaded. Events (including timers) are queued up while a script is executing. So your while loop will never terminate because the timer events that would update it will be waiting to fire until it finishes executing!

Even if that weren't the case, you'd still have ten timers each running forever.

You were on the right track with your first method. You just need to stop the timer:

function _initCountUpUsers()
{
    var totalUsers = $('#totalUsers');
    var ceiling = parseInt(totalUsers.html());
    var floor = ceiling - 10;

    function updateTotalUsers()
    {
        if(floor < ceiling)
        {
            totalUsers.html(floor);
            floor++;
        }
        else
        {
          window.clearInterval(timerID); // stop firing the timer once per second
        }
    }

    var timerID = window.setInterval(updateTotalUsers, 1000, floor);
}

If you're looking for slightly cleaner / less error-prone way to write this, just code yourself up a little helper routine:

function while_interval(proc, int)
{
  var timerID = setInterval(function()
  {
    if ( !proc() ) clearInterval(timerID);
  }, int);
}

...and call it like so:

while_interval(function()
{
  if (floor < ceiling)
  {
    totalUsers.html(floor);
    floor++;
    return true;
  }
}, 1000);

This lets you abstract away a tiny bit of housekeeping code, but more importantly it forces you to consciously return true as long as you wish the interval-loop to keep executing.

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

2 Comments

nice routine at the bottom of your post, and I've copied/pasted it - but there's a bug: where you say "clearTimer(timerID);" it should be "clearInterval(timerID);"
Thanks @Andy! Years later, someone finally notices - fixed! Don't hesitate to suggest edits that correct trivial errors like that, btw.
-1
function _initCountUpUsers()
{
    var totalUsers = $('#totalUsers'),
        ceiling = parseInt(totalUsers.html()),
        floor = cieling - 10,
        intRef = null;

    function updateTotalUsers()
    {
        if(floor < ceiling)
        {
            totalUsers.html(floor);
            floor++;
        }
        else {
            window.clearInterval(intRef);
        }
    }

    intRef = window.setInterval(updateTotalUsers, 1000);
}

or

function _initCountUpUsers()
{
    var totalUsers = $('#totalUsers');
    var ceiling = parseInt(totalUsers.html());
    var floor = cieling - 10;
    var int;

    function updateTotalUsers()
    {
        if(floor < ceiling)
        {
            totalUsers.html(floor);
            floor++;
            window.setTimeout(updateTotalUsers, 1000);
        }
    }

    window.setTimeout(updateTotalUsers, 1000);
}

1 Comment

Yeah, that's the method he said worked... And if you're gonna switch to setTimeout, it's probably worth putting in the extra code to adjust for timer lag.

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.