Set Interval (setInterval) 4ms Minimum Value

Hi there, I was trying to set intervals on different elements to count from 0, by creating a function that accepts the element ID, the number you wants the function to count to and the duration time you want the function to finish counting in.

For example, you want to count to 5000 in just 5 seconds, the function will calculate the suitable interval value to finish the task in the given time, when calling the function on 4 elements, three of them finish at the same time, while the element with the biggest value keeps counting in almost 40 seconds, even though they share the same core function.

Here’s the function:

$w.onReady(function () {
    $w('#productsNumber').text = '0';
    $w('#collectionNumber').text = '0';
    $w('#variantsNumber').text = '0';
    $w('#countriesNumber').text = '0';
    
    countUp('#productsNumber', 1793, 5);
    countUp('#collectionNumber', 202, 5);
    countUp('#variantsNumber', 9864, 5);
    countUp('#countriesNumber', 69, 5);
});

function countUp(elementId, endNum, endIn) {
     let i = 0;
     let intervalDuration = (endIn * 1000) / endNum;

    $w(elementId).onViewportEnter((event) => {
        setInterval(() => {
            if (i <= endNum) {
                 let value = String('+') + i.toLocaleString().toString();
                 $w(elementId).text = value
                 i++;
            }
        }, intervalDuration)
    })

}

So the bigger the number, the smaller the interval will be, the first thing that came into my mind, is that there’s a minimum value for the interval duration that the function will accept, I searched the web but found nothing in this regard.

But upon my calculations, any value of the interval less than 4ms will be ignored, and the default 4ms value will be used, that’s the only explanation for taking 40 seconds to count to 10000 as given above, but why? Why there’s a minimum value? And if it’s true, why it’s 4ms?

Regardless of the above, is there a way around to overcome this limitation?

Help is appreciated.
Ahmad

Hey @ahmadnasriya , you never cease to amaze me. :blush:

This really isn’t a Corvid issue, but it is a developer issue, and you’ve piqued my interest…

Here’s a really good discussion about this issue which you might find interesting: See the article WindowOrWorkerGlobalScope.setTimeout() and then search for " Reasons for delays longer than specified ".
ys longer than specified
I hope this helps. Take care and keep doing cool stuff.

The 4ms minimum interval is mentioned in many places, however as Yisrael states above, have a read of the pages linked and you should get a good understanding of it and how to workaround it.

Note as stated on the pages too, that if you want to get this to work in any device used which includes older devices still running on say Internet Explorer, then you will have to look into using a Polyfill to enable the HTML5 functionality.

Also, you will see on those linked pages that you can use window.postMessage to get a 0ms timeout.

To implement a 0ms timeout in a modern browser, you can use window.postMessage() as described here.

========================================================

Note: The minimum delay, DOM_MIN_TIMEOUT_VALUE, is 4 ms (stored in a preference in Firefox: dom.min_timeout_value), with a DOM_CLAMP_TIMEOUT_NESTING_LEVEL of 5.

Note: 4 ms is specified by the HTML5 spec and is consistent across browsers released in 2010 and onward. Prior to (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2), the minimum timeout value for nested timeouts was 10 ms.
(8.6 Timers:
The setTimeout() and setInterval() methods allow authors to schedule timer-based callbacks…
…Timers can be nested; after five such nested timers, however, the interval is forced to be at least four milliseconds.
…This API does not guarantee that timers will run exactly on schedule. Delays due to CPU load, other tasks, etc, are to be expected…)

=========================================================

Delay restrictions
It’s possible for intervals to be nested; that is, the callback for setInterval() can in turn call setInterval() to start another interval running, even though the first one is still going. To mitigate the potential impact this can have on performance, once intervals are nested beyond five levels deep, the browser will automatically enforce a 4 ms minimum value for the interval. Attempts to specify a value less than 4 ms in deeply-nested calls to setInterval() will be pinned to 4 ms.

Browsers may enforce even more stringent minimum values for the interval under some circumstances, although these should not be common. Note also that the actual amount of time that elapses between calls to the callback may be longer than the given delay; see Reasons for delays longer than specified in WindowOrWorkerGlobalScope.setTimeout() for examples.

========================================================

Reliability & timeout clamping
This API does not guarantee that timers will run exactly on schedule. Delays due to CPU load, other tasks, etc, are to be expected. Additionally a setTimeout or setInterval call has a minimum interval of of 4 ms, as specified by the HTML4 spec.

Generally all browsers implement this timeout “clamp” to 4 ms, although some browsers also clamp to a higher value when the window is not focused. For instance, the minimum timeout for a setInterval call can be up to a second in Chrome when the tab is inactive.

Hey @yisrael-wix , Thanks for your rich and informative reply.

I know that it’s not really a Corvid issue, or even a code issue, I just thought it might be some sort of limitation, and since my code is Corvid related, I thought it’s the best place to see what other people in the community say in this regard.

And thanks for the compliment, glad that I amaze you :kissing_closed_eyes:. Even though there’s nothing to be amazed by :thinking::wink:

Thanks for your reply @givemeawhisky , the information in your reply is exactly the same as the given by @yisrael-wix , I read it and found it very useful.

Thank you both for your valuable replies :kissing_closed_eyes: