1

So, I'm trying to use create a loop which does this:

setTimeout(function() {           
    console.log("Hey!");

    setTimeout(function() {           
       console.log("Hey!");

       setTimeout(function() {           
       console.log("Hey!");

       }, 1000);

    }, 1000);

 }, 1000);

So, I tried it like this.

for (i = 0; 1 < 3; i++){
    setTimeout(function() {           
    console.log("Hey!");
}, 1000);
}

How ever, it's not working.

Doing some research I've noticed this is because the timeOuts are getting added to each other with each loop. How can I work around this?

hyenax
  • 157
  • 1
  • 9
  • 1
    try i * 1000 instead of a fixed 1000 inside the loop. The question would remain Why though? What problem will this solve? And why are nested timeouts preferred over a setInterval() ? You';ll never get exact timings at 1sec 2sec 3sec either case though. – Shilly Nov 09 '18 at 14:05
  • Maybe just name the timeout function `setTimeout(functionToRun,1000) function functionToRun(){console.log('Hey');setTimeout(functionToRun,1000);` – user3647971 Nov 09 '18 at 14:06
  • Possible duplicate of [How to create pause or delay in FOR loop?](https://stackoverflow.com/questions/10058753/how-to-create-pause-or-delay-in-for-loop) – Alexander Nov 09 '18 at 14:07
  • Well, I'm using it to add classes, triggering animations, thereby a random bubble effect. Each animation should trigger 1s later than the other. – hyenax Nov 09 '18 at 14:07
  • "Each animation should trigger 1s later than the other. "...you might be better with a pattern involving Promises and callbacks – ADyson Nov 09 '18 at 14:10
  • 1
    _“Each animation should trigger 1s later than the other.”_ - then use the `animation-delay` property, instead of trying to assemble this using JS timeouts. – misorude Nov 09 '18 at 14:10
  • If the animations just have to start when the previous one ended, I would use promises. – Shilly Nov 09 '18 at 14:10
  • Too much tree climbing going on butt first. – user3647971 Nov 09 '18 at 14:10
  • Also, you could use solution from [How do I add a delay in a JavaScript loop?](https://stackoverflow.com/questions/3583724/how-do-i-add-a-delay-in-a-javascript-loop) topic. – Alexander Nov 09 '18 at 14:16
  • Super minor, but there's a typo above: `1 < 3;` should be `i < 3` – pixelbandito Nov 09 '18 at 14:20

3 Answers3

1

You have to recursively call the time outs, so write a function that takes an argument of the current number of attempts. Have it do an operation, and then call itself with the attempts argument += 1.

You should pass a number of attempts as a safeguard so you can tell the function not to call itself if the attempts number is > some limit, to avoid infinite loops.

Something like:

timedLog(attempts) {
  console.log('Hey!');
  if (attempts > 10) {
    return;
  } else {
    setTimeout(function() { timedLog(attempts + 1); }, 1000);
  }
}

It doesn't look like a for loop anymore, but it's the same principle.

pixelbandito
  • 480
  • 6
  • 12
  • I need the loop though, since in the larger code I will use the loop to add classes. – hyenax Nov 09 '18 at 14:10
  • Anything you can do in the loop, you can do here. For instance, you can treat `attempts` in the above code as `i` in your example. Just make your initial call with the argument 0, i.e. `timedLog(0)`, and `attempts` will be 0 on the first call, 1 on the second call, etc, up to the limit 10. If you have more info about what you need `loop` code for, let us know. – pixelbandito Nov 09 '18 at 14:17
  • This is the code I want to get into the loop: https://codepen.io/dario-sanchez-martinez/pen/WYxxQy – hyenax Nov 09 '18 at 14:20
  • 1
    Here's an edited codepen (I moved the JavaScript to the right column to make it easier to read): https://codepen.io/pixelbandito/pen/VVjKpd I changed the var name `attempts` in my loop to `i` and the other logic all stayed the same. – pixelbandito Nov 09 '18 at 14:34
  • Thanks! That works indeed :) I see you've changed it into an object instead? – hyenax Nov 09 '18 at 14:39
0

If the output of each function is the same, and you want to print it in the same interval, then you could use setInterval.

function myInterval() {
  return setInterval(function(){
    console.log("Hey!");
  }, 1000);
};

var id = myInterval();

It will repeat forever, so you would have to stop it, in this case, after 3000ms.

setTimeout(function(){
   clearInterval(id);
}, 3000);
EmmanuelB
  • 1,236
  • 9
  • 19
  • Heya, the loop is already happening in an interval of 5s. Here you can it in action: https://codepen.io/dario-sanchez-martinez/pen/WYxxQy – hyenax Nov 09 '18 at 14:09
  • I don't understand you comment, could you please explain? Do you want it to happen in an interval of 5s? What is your desired and actual behavior? Why is my answer not complete? Thanks. – EmmanuelB Nov 09 '18 at 14:21
  • I need the for loop for a nodelist: const bubble = document.querySelectorAll(".theSunBubble"); So for each Index there's 1 sec between – hyenax Nov 09 '18 at 14:27
0

Just use a loop, increasing the timeout interval each time:

for (let i = 0; 1 < 3; i++){
    setTimeout(function() {           
        console.log("Hey!");
    }, i*1000);
}

(Note, that if your callback function depended on i, this won't work as expected if you use var instead of let in the for loop header. The reason is to do with closures - there are many questions about this on SO. But it works perfectly with let - and there are other simple enough fixes if for some reason you can't use let.)

Robin Zigmond
  • 17,805
  • 2
  • 23
  • 34