Offline

An alternative to Javascript's evil setInterval

If you use Javascript often you might have come across the need for delaying the execution of code within intervals of time with repetition. This is were the native setInterval function comes to use. Despite being useful in many applications, setInterval's shortcomings could blow up your application in some circumstances.

Why is setInterval evil?

Doesn't care whether the callback is still running or not

In some cases, the function might need longer than the interval time to finish execution. Consider using setInterval to poll a remote server every 5 seconds, network latency, unresponsive server and other variables might prevent the request from completing on time. What would happen is that you'll end up with a bunch of queued requests that may not necessarily return in order.

Ignores errors

If for some reason, an error occurs in part of the code that is called by setInterval, it wouldn't break and keeps executing the faulty code.

Isn't that flexible

On top of the previously mentioned shortcomings, I'd really appreciate if setInterval had an optional parameter for setting the number of repetitions instead of repeating infinitely.

A better implementation

So I implemented my own setInterval function which tackles the above mentioned shortcomings. It supports the expected setInterval parameters with an extra optional one for specifying the number of repetitions to be done.

function interval(func, wait, times){
    var interv = function(w, t){
        return function(){
            if(typeof t === "undefined" || t-- > 0){
                setTimeout(interv, w);
                try{
                    func.call(null);
                }
                catch(e){
                    t = 0;
                    throw e.toString();
                }
            }
        };
    }(wait, times);

    setTimeout(interv, wait);
};

The interval function has an internal function called interv which gets invoked automatically via setTimeout, within interv is a closure that checks the the repetition times, invokes the callback and invokes interv again via setTimeout. In case an exception bubbles up from the callback call the interval calling will stop and the exception will be thrown.

This pattern does not guarantee execution on a fixed interval of course, yet it does guarantee that the previous interval has completed before recursing, which I think is much more important.

Usage

So to execute a piece of code 5 times with an interval or 10 seconds between each you would do something like this:

interval(function(){
        // Code block goes here
    }, 1000, 10);

Hope you find this snippet useful, feel free to leave your comments below.

References

Enjoyed this post? Help me spread the word and let me know your feedback!

Subscribe via