requestAnimationFrame schedules a callback for the browser’s render cycle. Unlike setInterval, each callback runs once, so the update method must request the next frame itself. section 4.5
A self-rescheduling visual countdown
Initialize a timer at 200, update the element’s width on each callback, reset it when it reaches zero, and schedule update again with requestAnimationFrame. The result is a green component that shrinks each frame and then restarts. section 4.5
Listing 4.9. Swapping setInterval for requestAnimationFrame
<html>
<head>
<title>Visual Countdown Timer</title>
<script>
class VisualCountdownTimer extends HTMLElement {
connectedCallback() {
this.timer = 200;
this.style.backgroundColor = 'green';
this.style.display = 'inline-block';
this.style.height = '50px';
requestAnimationFrame( () => #1
this.update());
}
update() {
this.timer --;
if (this.timer <= 0) {
this.timer = 200;
}
this.style.width = #2
this.timer + 'px';
requestAnimationFrame( () => #3
this.update());
}
customElements.define('countdown-timer', VisualCountdownTimer);
</script>
</head>
<body>
<countdown-timer></countdown-timer>
</body>
</html>
The listing shows the complete swap from setInterval to a recurring requestAnimationFrame update loop. section 4.5

