Creating a self-correcting alternative to JavaScript’s setInterval

Recently, I’ve been toying with JavaScript’s setInterval method which, if you’re unfamiliar, allows you to execute code repeatedly at a specified time interval. For example, one might create an interval which executes every second by using the following code snippet:

Both setInterval and its close cousin setTimeout suffer from latency caused by JavaScript’s single-threaded nature. While you may intend for an interval to execute every 1000 milliseconds, in reality it could take slightly longer for the function to be triggered. This is typically only a few milliseconds and therefore might appear to be a negligible problem. You might also expect that subsequent intervals would make an effort to get the code execution back on a predictable schedule. In other words, if there was 1007 milliseconds between registering the interval and the first code execution (a delay of 7 milliseconds), you could expect the next execution to occur as close to 2000 milliseconds as possible (i.e. 993 milliseconds later).

Depending on your browser, however, this may not be the case. We can demonstrate this by tracking the number of milliseconds which have passed since setInterval was registered:

If you run this in current versions of Chrome, Safari, Internet Explorer, or Node.js, you’ll notice that the interval execution grows increasingly out of sync with the original setInterval function call.

In my testing, I’ve found that only Firefox attempts to keep the interval execution in sync.

Regardless of whether this is the intended behavior of setInterval, I needed a means by which I could execute code as closely as possible to a predictable interval. Below is my solution to this problem:

Including the code sample above will add a new setCorrectingInterval function to the window global that can be called using the same parameters you would normally pass to setInterval. Here’s a detailed breakdown of what’s going on in the new function:

To track properties related to this particular interval instance, we wrap the inner tick function inside a closure construct.

When the function is first called (i.e. when instance.started is false), a number of properties are stored to our instance object.

In place of setInterval, we repeatedly call setTimeout, passing the tick function and an adjusted delay.

The adjusted delay is calculated by tracking both the start time of the original function call and an incremented target execution time.

To achieve the desired behavior, we can update the broken example to use setCorrectingInterval in place of setInterval.

2 thoughts on “Creating a self-correcting alternative to JavaScript’s setInterval”

I found your article today (four years later! Late November 2017) after going down a rabbit hole of wondering why setInterval seems to run faster in Chrome than node.js. To update your list of browsers, it looks like Chrome and Firefox use this feature, while Safari (and node) do not.

This is a neat function. The only problem is that, as far as I can tell, it is not possible to stop such a process. You need the ID returned from setInterval in order to stop it. In this case, it is a recursive function with no base case, and so you’ll never get an ID back.

Instead, I’m passing a control object, { run: true }, into the function, so that tick() can decide to not trigger the next setTimeout(). It works very well, but requires that extra argument.

Overall, this post saved me many hours. I was quite deep into the rabbit hole when I found it. It’s allowing me to more easily keep clients synced with the server in an online game. Please thank your four-years-younger self for me when you get a chance. Cheers!

Hi Daniel, thanks for the comment, I’m glad you found it useful! If I understand the problem you describe, I think this should be satisfied in the more complete `correctingInterval` project I published to GitHub / npm, which both returns an ID from `setCorrectingInterval` and includes a `clearCorrectingInterval` to allow you to stop it.