Sergey Scopin
Sergey Scopin

Reputation: 2245

Jquery usage of setTimeout in loop

I want to change value of p from 10 to 1 with delay 10 seconds.

for (var i=0;i<9;i++) {
    setTimeout(function(){$('#timer').text(10-i)}, 1000);
}

It takes value 1 for 1 second, I want it to become 10 then 9 then 8 etc. Here is fiddle. What's my mistake?

Upvotes: 0

Views: 93

Answers (6)

Chima
Chima

Reputation: 65

var breakPoint =60;
(function delay(bk){
    var counter=0;
    var handle = setInterval(function(){
    if( counter < bk){
        counter +=1;
        $('#timer').text(bk-counter);  
      }
 else{
        clearInterval(handle);
     }
 }, 1000);  
 }( breakPoint ) );

Upvotes: 0

Evgeniy
Evgeniy

Reputation: 2921

Its common problem for such cases when you need to use sync processed data in async methods. In you case you raise loop - its sync process, it increases i and run code you place text to closing bracket. So for increase i and run you code on each iteration. On every iteration you set new timeout, should be run in some time, its async. So what happening on first setTimeout start ? - Loop had already finished, i is already 10 and setTimeout use its callback.

To resolve this task you have to use closure - immediately invoke function witch be called on every iteration with i as param, and setTimeout inside this function. In this case param you passed will be stored in scope and could be used in timeout callback:

var timerNode = $('#timer'),
    stepInSec = 1;

for (var i=10; i>=0; i--) (function(t) {
  window.setTimeout(function() {
    timerNode.text(t);
  }, (10-t)*stepInSec*1000)
}(i)) 

Upvotes: 0

Alok
Alok

Reputation: 522

Use setInterval for achieving this as :-

    var i=0;
     var timer= setInterval(function(){
          i++;
          if(i==10){
            clearInterval(timer);    
          }
          $('#timer').text(10-i); 
      }, 1000);

In your code the for-loop wouldn't wait for the setTimeout to complete . hence by the time setTimeout waits .. for loop is over . hence after one second as for loop is over ..the value of i is 9 and 10-9=1 is shown ..

Here is link http://jsfiddle.net/1g8e7qy4/22/

Upvotes: 1

Barlas Apaydin
Barlas Apaydin

Reputation: 7315

You can use a recursive function to build this function:

Here is working jsFiddle.

var timing = 11;

function timingRun() {
    if ( timing > 0 ) {
        timing--;
        $('#timer').text(timing);
        setTimeout(function() {
            timingRun();
        },1000);
    }else{
        // if you need a loop add these lines
        timing = 11;
        timingRun();
    }
}
timingRun();

Upvotes: 0

Beri
Beri

Reputation: 11620

Sorry, but I have found another solution:) I hope it satisfies you.

var count = 10;

function run(){
    $('#timer').text(count--);
    if(count>=0) {
        setTimeout(run, 1000);
    }
}
run();

Upvotes: 1

Amit Joki
Amit Joki

Reputation: 59252

You need something like this, which uses setInterval and which also cares for memory leaks, by clearing the interval out.

var i = 10, intId = setInterval(function () {
    if (i > 0) $('#timer').text(--i); else clearInterval(intId);
}, 1000);

DEMO

Upvotes: 1

Related Questions