30

I would like to create a pause inside a while loop so that I can create n animations that each appear 3 seconds after the other.

I've tried the following, but it doesn't work. Would love to have someone show me what I'm doing wrong.

i=0;
while (i < n) {
    someanimation();
    setTimeout(function(){
        i++;
    }, 3000);
     
};
1

7 Answers 7

45

setTimeout does not pause; it asks Javascript to run some other code later.

Googling for "setTimeout loop" tells you exactly what you need to know. If you look around a little bit, it even mentions setInterval. The difference: using setTimeout to loop will wait 3 seconds in between loops, whereas setInterval will make it take 3 seconds total for the loop (including however much time the animation takes, as long as it's less than 3 seconds :) ). Also, setInterval constructs an infinite loop that you'll have to break out of after the desired number of times; setTimeout requires you to construct the loop yourself.

i = 0;

// setTimeout approach
function animation_loop() {
  someAnimation();
  setTimeout(function() {
    i++;
    if (i < n) {
      animation_loop();
    }
  }, 3000);
};
animation_loop();

// setInterval approach
i = 0;
someAnimation();
iid = setInterval(function() {
  i++;
  if (i < n) {
    someAnimation();
  } else {
    clearInterval(iid);
  }
}, 3000);
Sign up to request clarification or add additional context in comments.

3 Comments

you rock!! thank you so much - I'm a real beginner, so I'm not familiar with the idioms and I don't always know what are the best keywords to google. Anyway, you really unblocked me in a big way!!
This answer introduces an infinite setInterval. I'ts better to clear the setInterval when i >= n.
@A1rPun agreed; I updated the code to include that (and a bit clearer labelling of what's going on).
11

setTimeout is a little trickier than that because it doesn't block (i.e. it doesn't finish waiting on the timeout before continuing with the program).

What you want is closer to this:

var i = 0;
function nextFrame() {
    if(i < n) {
        someanimation();
        i++;
        // Continue the loop in 3s
        setTimeout(nextFrame, 3000);
    }
}
// Start the loop
setTimeout(nextFrame, 0);

It may also be worth your while to read up on setInterval as a possible alternative.

Comments

9

Well, thanks to ES6-7 with Promises we can now make a pause and make it look nice at the same time!

var id = 0;

async function do() {
  while(true) {
    await pause(id);
    //will happen only after pause is done
    id++; 
  }
}
function pause(id) {
  return new Promise(resolve => setTimeout(() => {
    console.log(`pause ${id} is over`);
    resolve();
  }, 1500)); 
}

do();

Comments

5

One of the way of doing it is to use RxJS. Please take a look at working example here

Rx.Observable
  .interval(1000)
  .take(10)
  .subscribe((x) => console.log(x))

Comments

0

You are not very specific about what you want to do, but I'd say the main problem is that you call someanimation() without a delay. So maybe this solves it for you:

for (var i = 0; i < n; i++) {
    setTimeout(someanimation, 3000 * i);
};

Note the missing () after someanimation as it is the callback for setTimeout().

8 Comments

Please don't reinvent something for which there are standard idioms.
@Karl Knechtel: what are you talking about? What "standard idioms"? Yours is the same idea. The only difference is that you launch the next call to someanimation() in the timer function.
"...you launch the next call to someanimation() in the timer function." That's exactly what the standard idiom is. That way, only one callback is enqueued at a time.
This will enqueue all of the iterations at the same time and then wait 3 seconds to dump out the calls to someanimation at the same time.
@BrettMathe *sigh* jsfiddle.net/fw4mmgca Just watch the timestamp. And please get your facts straight, before you downvote the next time.
|
0

create a function like:

function sleep_until (seconds) {
   var max_sec = new Date().getTime();
   while (new Date() < max_sec + seconds * 1000) {}
    return true;
}

and then change your code to

i=0;
while (i < n) {
    someanimation();
    sleep_until(3);
    do_someotheranimation();
};

2 Comments

blocking the js was precisely what i happened to be looking for.
Sometimes you do want to block the engine.. (hopefully just for testing)
0
function myFunction() {
    var x;
for(var i=0;i<10;i++){
    if (confirm("Press a button!") == true) {
        x = "You pressed OK!";
    } else {
        x = "You pressed Cancel!";
    }
    document.getElementById("demo").innerHTML = x;
}
}``

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.