SetTimeout is not on time, CSS accurately realizes the timer function

In the actual development process, we often encounter requirements such as entering the page for the first time to give corresponding prompts, and then disappearing automatically after a specified time or displaying the front-end clock.

According to the traditional scheme, we can use setTimeoutthe implementation . But it exists: the actual delay is longer than the set value.

setTimeout is not on time

There are many factors that can cause setTimeout callbacks to take longer than expected.

Minimum delay >= 4ms

  1. If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4. – HTML5 spec Timers

In the browser, because the function is nested to a certain depth, it will be blocked.

function cb() {
    
     
  setTimeout(cb, 0)
}
setTimeout(cb, 0)

Timing minimum delay for inactive tabs >=1000ms

In order to optimize the tab loading loss (and reduce power consumption), the minimum delay of the timer in the inactive tab is limited to 1S (1000ms).

timeout delay

In addition to the "minimum delay", the timer may still be delayed because the current page (or the operating system/browser itself) is occupied by other tasks.

It should be emphasized that callback functions and code sections cannot be executed until the setTimeout()calling main thread has finished performing other tasks.

Maximum delay value

Browsers including IE, Chrome, Safari, and Firefox store delays internally as 32-bit signed integers. This will cause an overflow if a delay is greater than 2147483647 milliseconds (about 24.8 days), causing the timer to be executed immediately. -- The setTimeout/setInterval delay value is too large

Breaking the 4ms limit

If you want to implement a 0ms delay timer in the browser, you can try the following method

(function() {
    
    
  var timeouts = [];
  var messageName = "zero-timeout-message";

  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);

  window.setZeroTimeout = setZeroTimeout;
})();

CSS is more punctual

If you want to implement a particularly punctual business scenario (such as a clock ). Obviously setTimeout/setInterval is not the best practice. How to avoid synchronous blocking is an important point to break through this problem.
insert image description here

Here, using CSS animation to achieve, CSS animation has several significant advantages:

  1. Does not rely on javascript, and has mature related APIs;
  2. Works well, even on low performance systems. The rendering engine will use frame skipping or other techniques to ensure that the animation performance is as smooth as possible;
  3. Lets the browser control the animation sequence, allowing the browser to optimize performance and effects, such as reducing the frequency of animation updates located in hidden tabs.

The animation attribute is a shorthand attribute form of the animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, animation-fill-mode, and animation-play-state attributes.

Attributes illustrate example
animation-name Specifies a sequence of animations to apply animation1,animation2
animation-duration Specify the duration of an animation cycle in s or ms 60s
animation-timing-function The cadence to execute in each animation cycle easelinearsteps(60)
animation-delay Define when the animation starts, in s or ms 100ms
animation-iteration-count Defines the number of times the animation will run before ending infinite(unlimited times),3
animation-direction Indicates whether the animation plays in reverse normalalternatereverse
animation-fill-mode Sets how CSS animations apply styles to their targets before and after execution forwardsbackwards
animation-play-state Defines whether an animation is running or paused runningpaused
animation: timer 60s infinite steps(60) forwards;

steps(number_of_steps, direction): Defines a step function that divides the domain of output values ​​equidistantly.

insert image description here

Bind the value to be displayed via a custom data property. In this way, in css, expressions can be used attr()to obtain values.

<div class="container">
  <p data-seconds="00 01 02 03 04 05 06 07 08 09"></p>
</div>

The current value is displayed through a pseudo-element (only one is displayed at a time), and then the duration of the animation cycle is 10s, and the equidistant division is divided into 10 steps.

The ordinate of the moving vector every 1s.

.container p {
    
    
  height: 68px;
  width: 68px;
  line-height: 68px;
  overflow: hidden;
}
.container p::after {
    
    
  display: block;
  content: attr(data-seconds);
  animation: timer 10s infinite steps(10) forwards;
}

@keyframes timer {
    
    
  from {
    
    
    transform: translate3d(0, 0, 0);
  }
  to {
    
    
    transform: translate3d(0, -100%, 0);
  }
}

Guess you like

Origin blog.csdn.net/ligang2585116/article/details/130481543