A setInterval() alternative for browser-based games
Don’t use setInterval()
for your game loops. In JavaScript,
timers operate in a non-guaranteed delay manner due to the
single-threaded nature of the language in browsers.
Asynchronous events such as timers and mouse clicks can
only be executed when there is a gap in the execution.
Consider the following example where we want to calculate the number of seconds elapsed since a certain date:
It would seem like this function increments count
every second,
but setInterval()
only guarantees that the it will wait
at least one second—not that it will wait exactly one second.
If you have a game that assumes the time is the same for all players regardless of browser or device, you’ll want a more robust solution.
So let’s create just that, and call it setInterval2()
.
Precision interval-based function invocation instructions
Start by creating a const function with the same arguments
we would pass to setInterval()
: the function it should
invoke after each interval, and the length (in milliseconds)
of each interval between executions:
Next, let’s create a way to execute the provided function as well as schedule the next execution of that function after a specific time:
The wrapper
function dynamically adjusts the timeout for
each iteration beyond the first based on the actual time
elapsed. This helps compensate for inconsistencies caused by
the single-threaded nature of JavaScript and the imprecision
of timers.
We still need to handle the first iteration, and then
wrapper
will be on its recursive way:
Finally, let’s provide a way to halt any additional
executions. We can do this by wrapping a clearTimeout()
in an anonymous function and returning it:
Putting it all together, you should end up with something like this:
If you’d like to try it out, just open up your browser’s developer tools—where you’ll see it’s been running this whole time.
Here’s how I did it:
Now go forth and make some great games.