- En JavaScript,
setTimeout(0) ne s’exécute pas réellement immédiatement et subit souvent un délai minimal de 4 ms, une limite par défaut imposée par les navigateurs pour éviter les abus
- Cette contrainte vise à empêcher les sites web d’abuser des timers de façon incontrôlée et de provoquer une consommation de batterie excessive ou une dégradation des interactions ; elle peut être renforcée à 16 ms en mode batterie et à 1 seconde dans les onglets en arrière-plan
- Pour contourner les limites de
setTimeout, les développeurs ont utilisé diverses API de timers alternatives comme setImmediate, MessageChannel.postMessage, window.postMessage et scheduler.postTask
- D’après les benchmarks réels, Chrome et Firefox appliquent un clamp à 4 ms, mais
MessageChannel et scheduler.postTask fonctionnent presque sans latence, tandis que Safari limite setTimeout de façon plus agressive
- Au fond, il s’agit d’un problème d’équilibre entre la protection de l’expérience utilisateur et la liberté des développeurs ; aujourd’hui, la Scheduler API s’impose comme solution standardisée, même si de nouvelles interventions des navigateurs (Intervention) pourraient apparaître en cas d’abus
Contexte des limitations de setTimeout
L’apparition d’autres API de timers
setImmediate : pris en charge uniquement par IE et l’ancien Edge, aujourd’hui pratiquement abandonné
MessageChannel.postMessage : transmet une tâche à la boucle d’événements via un canal séparé
window.postMessage : bonnes performances, mais risque de conflit avec d’autres scripts
scheduler.postTask : pris en charge par les navigateurs récents et considéré comme le choix le plus fiable
Résultats des benchmarks (MacBook Pro 2021, 101 itérations)
- Chrome 139 :
setTimeout 4.2ms, scheduler.postTask 0ms
- Firefox 142 :
setTimeout 4.72ms, scheduler.postTask 0.01ms
- Safari 18.4 :
setTimeout 26.73ms, MessageChannel 0.52ms, window.postMessage 0.05ms
Le cas de fake-indexeddb
- IndexedDB souhaite un commit automatique de transaction juste après la fin des microtasks de la boucle d’événements
- Le
setImmediate de Node.js est idéal, mais dans le navigateur setTimeout est inefficace
- Dans Chrome, une tâche qui prend 300 ms peut s’allonger jusqu’à 4,8 secondes dans le navigateur
- Comme solution,
scheduler.postTask est utilisé par défaut, avec MessageChannel/window.postMessage comme fallback pour la compatibilité
Le débat sur l’intervention des navigateurs
- Un camp affirme qu’il faut limiter les timers pour que les développeurs soient protégés d’eux-mêmes
- L’autre estime qu’il faut garantir la liberté des développeurs afin qu’ils puissent mesurer et optimiser par eux-mêmes
- Au final, selon le principe de priorité à l’utilisateur, les navigateurs interviennent pour empêcher les abus
- La Scheduler API tente de concilier ces deux positions en donnant aux développeurs un contrôle fin des tâches tout en s’alignant sur le pipeline de rendu du navigateur
Perspectives
postTask et postMessage devraient rester sans throttling pendant un certain temps
- Mais un abus de priorités élevées comme
user-blocking pourrait entraîner de nouvelles interventions
- À long terme, une autre API alternative comme
scheduler2 pourrait devenir nécessaire
Aucun commentaire pour le moment.