views:

72

answers:

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);       
    }

}
A: 
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);
}
andres descalzo
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.
Shog9
+1  A: 

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() ) clearTimer(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.

Shog9