0

Can you please take a look at following code and let me know how I can avoid the delay on only FIRST time of this counting down process?

As you can see the counter works fine but there is a delay on first time starting.

var sec = 20;
var timer = setInterval(function() { 
   $('#box').text(sec--);
   if (sec == -1) {
      $('#box').css('color','blue');
      clearInterval(timer);
   } 
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box">20</div>
Suffii
  • 5,694
  • 15
  • 55
  • 92

4 Answers4

7

Use --sec instead of sec--, so that the changed value will be set.

The reason why this is working is well described here: ++someVariable Vs. someVariable++ in Javascript

So your code should look like this:

var sec = 20;
var timer = setInterval(function() { 
   $('#box').text(--sec);
   if (sec == -1) {
      $('#box').css('color','blue');
      clearInterval(timer);
   } 
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box">20</div>
Community
  • 1
  • 1
friedi
  • 4,350
  • 1
  • 13
  • 19
  • 1
    I don't understand how will this solve the problem? Can you add an explanation? – Zee Jul 01 '15 at 09:07
  • Hi friedi, thanks but can u please let me know what is the magic here? does the `--sec` is really doing the job? – Suffii Jul 01 '15 at 09:08
  • 1
    @Zee the OPs code will require two passes of the timer to decrement the variable the first time - hence the delay. This decrements on the first pass to remove that delay. See an explanation of the difference in the operator position here: http://stackoverflow.com/questions/3469885/somevariable-vs-somevariable-in-javascript – Rory McCrossan Jul 01 '15 at 09:08
  • Essentially, `sec--` will evaluate the expression and *then* decrement the value, whereas `--sec` will decrement the value and *then* evaluate the expression. – jonny Jul 01 '15 at 09:26
3

Another option - move piece of code to separate function

var sec = 20;
var execution = function() {
   $('#box').text(sec--);
   if (sec == -1) {
      $('#box').css('color','blue');
      clearInterval(timer);
   } 

}

execution(); // Run first time without delay

var timer = setInterval(function() { 
    execution(); // every next run should be done with delay
}, 1000);
Anonymous
  • 1,823
  • 2
  • 35
  • 74
0

put the callback in a separated function and call it immediately after/before, as you like, the setInterval();

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

To answer your question: Instead of an anonymous function, use a function expression. This will allow you to call that function anywhere in your code.

To dig a bit deeper: Instead of setInterval, consider setTimeout. Intervals can queue up when the going gets tough (leading to some interesting results), timeouts won't. See John Resig's post on timers for more info.

A timeout setup (see a comparison in the snippet below):

var secs = 20,
onTimeout = function() { // a function expression
  console.log(secs);
  if (secs--) {
    // do things before complete here (~1x per sec)
    timeout = setTimeout(onTimeout, 1000);
  } else {
    // do things after complete here
  }
}, timeout;
onTimeout();

If you're after accuracy in a modern browser, use requestAnimationFrame.

/**
 OK: INTERVAL
**/
var secs_i = 20,
onInterval = function() {
  console.log(secs_i, 'Interval');
  if (secs_i--) {
    // do things before complete here (~1x per sec, may queue and run in fast succession)
  } else {
    return clearInterval(interval);
    // do things after complete here
  }
},
interval = setInterval(onInterval, 1000);
onInterval();


/**
 BETTER: TIMEOUT
**/
var secs_t = 20,
onTimeout = function() {
  console.log(secs_t, 'Timeout');
  if (secs_t--) {
    // do things before complete here (~1x per sec)
    timeout = setTimeout(onTimeout, 1000);
  } else {
    // do things after complete here
  }
}, timeout;
onTimeout();


/**
 BEST: ANIMATION FRAME (IE9+ everything else)
**/
var secs_a = 20,
onAnimationFrame = function() {
  time = secs_a - (window.performance.now() - init)/1000;
  console.log(time.toFixed(2), 'Animation Frame');
  if (time > 0) {
    // do things before complete here (~60x per second)
    af = window.requestAnimationFrame(onAnimationFrame);
  } else {
    // do things after complete here
  }
}, af, init = window.performance.now(), time;
onAnimationFrame();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><script>console.log=function(log,id){$('h1[data-id="'+id+'"]').text(log);};</script><h1 data-id="Interval"></h1><h1 data-id="Timeout"></h1><h1 data-id="Animation Frame"></h1><style>h1:before{content:attr(data-id)": ";}</style>
som
  • 2,023
  • 30
  • 37