setInterval vs requestAnimationFrame : que choisir pour un minuteur ?
Pour un minuteur en JavaScript, setInterval est simple mais imprécis, requestAnimationFrame est fluide mais limité au taux de rafraîchissement. Comparatif.
Pour rafraîchir l'affichage d'un minuteur ou chronomètre en JavaScript, deux primitives s'offrent au développeur : setInterval et requestAnimationFrame. Aucune n'est universelle ; le bon choix dépend de la précision visée.
setInterval — simple mais imprécis
setInterval(updateDisplay, 1000);
Avantages — API directe, faible CPU, idéal pour rafraîchir une fois par seconde.
Limites :
- L'intervalle réel peut dépasser 1000 ms si la page est chargée.
- Throttlé à 1 Hz dans un onglet en arrière-plan.
- Pas synchronisé avec le rafraîchissement écran : tearing possible.
requestAnimationFrame — fluide mais lié au refresh
function tick() {
updateDisplay();
requestAnimationFrame(tick);
}
tick();
Avantages — synchronisé sur le refresh (60 ou 120 Hz), animation fluide, économe en énergie sur écran inactif.
Limites :
- Mis en pause complètement quand l'onglet est en arrière-plan.
- Sur écran 60 Hz, ne tick que toutes les 16,6 ms.
- API moins intuitive (récursion).
La règle d'or : ne JAMAIS dériver le temps du compteur
Quelle que soit la primitive, le compte à rebours doit se calculer par différence avec une heure cible :
const endTime = Date.now() + duration;
function tick() {
const remaining = endTime - Date.now();
render(remaining);
if (remaining > 0) requestAnimationFrame(tick);
}
Si le navigateur saute un tick, le tick suivant rattrape automatiquement. Le compteur ne dérive jamais.
Recommandation
| Cas | API |
|---|---|
| Minuteur affiché à la seconde | setInterval(1000) + diff Date.now() |
| Chronomètre au centième | requestAnimationFrame + diff performance.now() |
| Animation visuelle (barre) | requestAnimationFrame |