1
    function generalFunctionThatHappensWhenYouClickAButton(){
        for (let i = 0; i < 1000; i++){
            setTimeout(animateSquares(), 10000);
        }
    }
    
    function animateSquares(){
          topPositionThatAdds++;
          console.log(topPositionThatAdds);
      }

The function animateSquares() will execute 1000 times as planned, but all at the same time and not waiting 10,000 ms for each execution, as I planned to.

Does anyone know why this is happening?

Thank you for your time.

Xavi Font
  • 33
  • 3
  • Your loop clearly states to run it 1,000 times. – EspressoBeans Nov 14 '20 at 04:10
  • @EspressoBeans yes I told the loop to run 1000, but wait 10,000 ms before each execution, and it is not respecting the time I want it to wait. – Xavi Font Nov 14 '20 at 04:13
  • You probably want to do something like this instead: https://stackoverflow.com/a/5226333/1188197 – EspressoBeans Nov 14 '20 at 04:14
  • You set timer for `animateSquares()`, but not for `for loop`. So all the `animateSquares()` is called at the same time. Search for documentation on how `setTimeout` works for detail – Daniel Sabrel Nov 14 '20 at 04:17
  • @EspressoBeans I think the link you provided would confuse OP even more, since the post in the link uses `alert` which stops all other execution of js functions – Daniel Sabrel Nov 14 '20 at 04:29
  • 1
    Another thing is that the () will immediately invoke the animateSquares method first of all, but removing them will only delay the first call. – Candace Ahrends Nov 14 '20 at 04:30
  • What @CandaceAhrends said is correct and is the only reason why your code inside setTimeout( ) is being executed immediately. Please see my answer for more details. – Link Nov 14 '20 at 04:44
  • @Link No offense here but your code calls all setTimeout functions immediately as well i.e doesn't wait for 10000ms = 10s – Daniel Sabrel Nov 14 '20 at 04:54
  • @DanielSabrel did you try to click on the `Run Code Snippet` from my answer? It waits for 10s.You need to understand that on each iteration of the for loop, a new timer of the setTimeout is started and set at 10s. So if the first setTimeout timer is set right now (say at 0 seconds) the next one will be set at 0.10(seconds or something basing on when that line of code is executed). I'll add a time log in milliseconds to my answer which will prove this. I believe you are confused on how the JavaScript Event Loop and Callbacks work. – Link Nov 14 '20 at 04:57
  • @DanielSabrel, please check my answer now, I've added a milliseconds log as well. If this doesn't answer your query, I would recommend you go through the following material for a better understanding how event loop, callbacks work in JS and how setTimeout works : 1) https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout 2) https://stackoverflow.com/questions/64756522/how-exactly-are-the-function-calls-ordered-in-an-asynchronous-javascript-program/64757187#64757187 – Link Nov 14 '20 at 05:02
  • 1
    @Link Please correct me if I am wrong. The question was to execute a function `animateSquares()` 1000 times at 10s interval. If this code really does that, then i am fine with it – Daniel Sabrel Nov 14 '20 at 05:04
  • if the OP wants each callback to have a 10ms delay between them, then he will have to increment the timeout ms he is supplying to the setTimeout function dynamically or, change the placement of setTimeout – Link Nov 14 '20 at 05:04
  • @DanielSabrel you're right, my bad. I corrected the code but missed the part where the OP said he wants 10 second delay b/w each call. I've fixed my answer now. It was a simple fix, to increment the timeout with the `'i'` from the for loop :) – Link Nov 14 '20 at 05:14

2 Answers2

0

Well, that is because inside your setTimeout function, you're not just specifying your handler/callback function, instead you are calling it. In case of any callback functions, if you call them using ( ), they will always be executed immediately.

Therefore, your code shouldn't be this:

setTimeout(animateSquares(), 10000);

Instead, it should be this:

setTimeout(animateSquares, 10000); //specify the callback, don't call it using ( )

As you want there to be a 10ms delay between each callback execution, you can go about that in the following way:

let topPositionThatAdds = 0;

function generalFunctionThatHappensWhenYouClickAButton() {
  for (let i = 0; i < 1000; i++) {
    setTimeout(animateSquares, 10000 * (i + 1));
  }
}

function animateSquares() {
  topPositionThatAdds++;
  console.log(
    topPositionThatAdds
  );
}

generalFunctionThatHappensWhenYouClickAButton();
Link
  • 1,048
  • 1
  • 14
0

Now if you wanted to use a parameter in your callback (topPositionThatAdds), then you can do something like the following.

function topPositionThatAdds(i){
        console.log('square ', i);
    };
    
function generalFunctionThatHappensWhenYouClickAButton() {
  for(var i = 0;i < 1000; i++){
      let j = i;
      setTimeout(
      function() {topPositionThatAdds(j)}
      , 10000 * (j + 1));
  }
}

generalFunctionThatHappensWhenYouClickAButton();
EspressoBeans
  • 922
  • 8
  • 20