JavaScript and more: 4 creative approaches to measuring time in browsers

The author of the article, the translation of which we are publishing today, decided to talk about several unusual ways of measuring time in browsers. To use them, you will need access to various APIs that are used in web development, so they are not suitable for the Node.js platform. True, if someone needs an unusual way of measuring time in Node.js, then, we believe, after reading this material he may have some ideas on this subject.



Using an infinite synchronous loop in a web worker (not in a service worker)


Since web workers are essentially threads running in a web browser, they can run endless loops without risking blocking the main thread. This allows you to work with periods of time, the duration of which is less than a millisecond. This accuracy is especially suitable for those cases when a worker needs to make decisions that are highly time-dependent. The adoption of these decisions can (with a very high level of accuracy) be reported to the main stream. For example, you can derive something in the case when the number of microseconds that have passed since a certain event is represented by a prime number. In order to work with microsecond accuracy over time, you can use the performance.now method .

â–ŤAdvantages


  1. Achievable accuracy expressed in microseconds.
  2. .
  3. , , . - .
  4. . , setInterval, terminate , . MDN : « terminate() Worker . , ».

â–Ť


  1. Even though this method makes it possible to work with time intervals that are less than a millisecond, sending messages to the main thread works asynchronously. That is, it is impossible to carry out certain actions in the main thread with the same accuracy with which the worker decides that these actions need to be performed.
  2. This method fully loads the stream, which can lead to increased battery consumption on phones.
  3. This method requires the support of web workers.
  4. An infinite loop in a web worker does not pause if the tab associated with it is inactive.

→ Example on Codesandbox

Using CSS animations for events related to time (in particular - animationiteration)


This method involves creating an element with endless animation. Here you can try to use the element div, but I must say that, as noted in paragraph 2 of the list of shortcomings of this method, divit is better not to use elements for these purposes. So, if we have an element with endless animation, we can subscribe to its event animationiterationand receive notifications at those moments when the interval expires animation-duration.

â–ŤAdvantages


  1. Automatically pause if the browser tab becomes inactive. In this case, the event of interest to us simply does not occur. Therefore, you do not need to worry about solving the problem of processing many events that have accumulated during the time when the tab was inactive and then activated.
  2. div DOM. , React-, , . div .
  3. , , . — :

    .addEventListener("animationiteration", fun).
  4. animation-delay.

â–Ť


  1. . , , .
  2. Dependence on DOM and CSSOM. Other CSS rules may affect those that describe the animation. Therefore, I advise you to create for the organization of the timer a kind of randomly named previously nonexistent tag like <just-a-timer-element></<just-a-timer-element>. Maybe - is it worth creating a custom element, inside which CSS animation code is neatly hidden? (all of these are pretty controversial ideas, actually).
  3. This method does not work if the element has a style display: none;.
  4. Inaccuracy. In accordance with my tests, the accuracy of the countdown can be about 1 ms. You, to find out exactly how it works for you, can experiment with an example, a link to which is given below.

→ Example on Codesandbox

Using the svg tag (SMIL animations)


Take a look at the following SVG element:

<svg>
  <rect>
    <animate
      attributeName="rx"
      values="0;1"
      dur="1s"
      repeatCount="indefinite"
    />
  </rect>
</svg>

If you use the following code:, animate.addEventListener('repeat', fun)then the function funwill be called every dursecond. In our case, every second.

â–ŤAdvantages


  1. This method works even if a style is assigned to the SVG element display: none;.
  2. The countdown automatically stops when the SVG element is removed from the DOM.
  3. Event generation does not start until the page is fully loaded.
  4. The "timer" is automatically paused if the tab becomes inactive.

â–Ť Disadvantages


  1. As in the case of counting time intervals using CSS animation, the application of this method may seem incomprehensible to other programmers.
  2. Dependence on DOM and CSSOM. That is - here we have the same undesirable features that have already been described for the method of counting time using CSS animation. Namely - the possibility of disruption of the "timer" due to other CSS-rules.
  3. It is not supported in IE and Edge (until the browser is transferred from Microsoft to Chromium).
  4. Inaccuracy. In accordance with my tests, the deviations of such a timer from the most accurate method can be very impressive 15 milliseconds. You can verify this yourself by experimenting with the example, a link to which is given below.
  5. The countdown does not start until the page is fully loaded. True, this “minus” of this method may turn out to be a “plus” in some situations.

→ Example on Codesandbox

Using Web Animations API


Web Animations API allows you to animate DOM elements using JavaScript code.

The interesting thing is that you can even animate unmounted elements! This gives you access to the time mechanisms available in pure JavaScript (and the Web API).

Here is an alternative implementation setTimeout:

function ownSetTimeout(callback, duration) {
  const div = document.createElement('div');

  const keyframes = new KeyframeEffect(div, [], { duration, iterations: 1 });

  const animation = new Animation(
    keyframes,
    document.timeline
  );

  animation.play();

  animation.addEventListener('finish', () => {
    callback();
  });
}

Neatly, right?

â–ŤAdvantages


  1. A self-contained solution that does not require interaction with the DOM.
  2. A programmer unfamiliar with this approach will easily understand the meaning of the corresponding code.
  3. "Timer" pauses on an inactive tab.

â–Ť Disadvantages


  1. Web Animations API - the technology is still experimental. Do not use it in production.
  2. Very poor browser support. This method is likely to work only in Chromium.
  3. With all the advantages of this solution, it, nevertheless, may seem to someone far from intuitive.
  4. The fact that the “timer” is paused on an inactive tab may turn out to be a minus of this solution if it is used as an alternative setTimeout.
  5. This method cannot be used to count intervals. Only an event is available to the programmer onfinish.
  6. Low accuracy. According to my experiments, the error can easily be ± 5 milliseconds.

→  Example on Codesandbox

Bonus


In order to work with time, you can use the Web Audio API. This is another great way to work accurately with intervals and delays. Here is a great article about it.

Summary


I understand that the techniques of working with time that I have listed here can benefit far from all. But I just could not help but write this article, because I always thought that setTimeoutand setInterval- these are the only ways to work asynchronously with certain periods of time. But in reality, as it turned out, this is far from all. Who knows, maybe someone will have to deal with some unusual restrictions when working on a certain project, with some special conditions in which the working methods highlighted here may prove useful over time.

Dear readers! In what situations do you think the time-based approaches described here can come in handy?


All Articles