I’m looking to animate a rendered image, so I need to control the timing of iterations, starting with a simple loop. The goal is to print the numbers 1 to 5, with 2-second intervals between each. You can run each code block by clicking the green button on the lower right corner of each cell.
The iteration is complete by the time
setTimeout is called, so all the numbers are logged on the console at the same time. Kind of defeats the point.
Global Variable Scope
Again, the iteration is complete by the time
setTimeout is called. At this point,
i has exceeded 5. It is able to bypass the callback because declaring
i as a
var makes it global. When the callback is executed, it is using the global variable value of 6. However, since the delay in `setTimeout` is incremented as
i increases, there is an actual time lapse between each printing of the number
6. I'm not completely lucid on every detail of this, but the rough idea is acceptable enough for me to move on.
This post explains why the code failed in the last block:
var i is hoisted and thus global. The
for loop has already completed and
i has reached
5, before the
setTimeout callback is executed. If I absolutely have to use
var i in the loop for some reason, the solution is to wrap the loop in a closure.
If I don't have to use
var in the loop, the easy solution is to use
let instead. I wouldn't have to change the rest of the code to add closure, because
let is block-scoped.
I've seen this type of code in the wild.
It's one of these moments, but the happy version of it:
Joel Spolsky has said that pointers and recursion are two concepts that some people are never able to fully comprehend. Kind of like "you're not a real programmer (but I am)."
Recursion With Stop
I've been told that the code in this function actually runs infinitely because of the recursion, but since it's not logging numbers on the console anymore, you just don't notice it. That can't be good, so here, I attempt to stop the function once I get the desired result. I'm not sure if the code has actually stopped running, but the
clearTimeout() hasn't broken anything.
All the snippets are available on this RunKit notebook.