Last Updated: January 29, 2019
·
5.189K
· codingjohnson

setTimeout(func, 0) will not work as expected

If you're trying to start a thread (or do something asynchronously) in Javascript then setTimeout(func, 0) and setInterval(func, 0) are not really the way to go since the HTML5 spec defines the lowest value allowable as 4ms.

There's probably not a lot of (visible) difference between 0ms and 4ms. But if you're using it for animation then please requestAnimationFrame - otherwise use this peice of magic from David Baron (2010)

// Only add setZeroTimeout to the window object, and hide everything
// else in a closure.
(function() {
    var timeouts = [];
    var messageName = "zero-timeout-message";

    // Like setTimeout, but only takes a function argument.  There's
    // no time argument (always zero) and no arguments (you have to
    // use a closure).
    function setZeroTimeout(fn) {
        timeouts.push(fn);
        window.postMessage(messageName, "*");
    }

    function handleMessage(event) {
        if (event.source == window && event.data == messageName) {
            event.stopPropagation();
            if (timeouts.length > 0) {
                var fn = timeouts.shift();
                fn();
            }
        }
    }

    window.addEventListener("message", handleMessage, true);

    // Add the one thing we want added to the window object.
    window.setZeroTimeout = setZeroTimeout;
})();

4 Responses
Add your response

Your code is not cross-browser nor tested. There are talks about introducing setImmediate function and a well-tested library that polyfills it

https://developer.mozilla.org/en-US/docs/Web/API/window.setImmediate

https://github.com/NobleJS/setImmediate

over 1 year ago ·

// If you're trying to start a thread // As far as I know, setTimeout(fn,0) technique is used to push the function execution at the end of the thread (not a new thread). And, isn't the JavaScript single threaded? :)

over 1 year ago ·

@twolfson I am aware it is not entirely cross-browser, and I would recommend the NobleJS implementation in a heartbeat (which uses something like the code above for browsers that support it). My intention was only to make other developers aware that there are problems with setTimeout and setInterval - but also that there are alternatives. Thank you for your contribution in making others aware. Also - I'm not sure Mozilla want to support it, see: It meets resistance both from Gecko (Firefox) and Webkit (Google/Apple).

@vraa you're correct, setTimeout and setInterval do not offer threading and Javascript is single threaded, although it can appear to the novice that the opposite is true. Therefore in my opening paragraph I refer to both asynchronicity and threads - my intention was avoid confusion, but I can see how it might be confusing.
Additionally, setTimeout and setInterval (even setImmediate) will push the execution at the end of a loop in Javascript, however, there is an imposed delay of (typically) 4ms. I'm aware that Chrome has tried to reduce this to 2ms but has had issues. I should also add that in some tests the postMessage implementation executes faster than the browser imposed delay in setTimeout and setInterval.

over 1 year ago ·

I believe David Baron's setZeroTimeout will work in IE8, which is completely fine! The lack of supporting IE9> really shouldn't be an issue with a plethora of mobile devices and rapidly upgrading browsers.

And what is wrong with Coderwall's comments??? The positioning is all janky!

over 1 year ago ·