16 Punkte von GN⁺ 2025-09-22 | Noch keine Kommentare. | Auf WhatsApp teilen
  • In JavaScript wird setTimeout(0) in der Praxis oft nicht sofort ausgeführt, sondern mit einer Mindestverzögerung von 4 ms, was eine grundlegende Browser-Beschränkung zur Verhinderung von Missbrauch ist
  • Solche Einschränkungen sollen verhindern, dass Websites Timer wahllos missbrauchen und dadurch Akkuverbrauch oder schlechtere Interaktionen verursachen; im Akkubetrieb kann die Grenze auf 16 ms steigen, in Hintergrund-Tabs sogar auf 1 Sekunde
  • Entwickler haben verschiedene alternative Timer-APIs genutzt, um die Grenzen von setTimeout zu umgehen, darunter setImmediate, MessageChannel.postMessage, window.postMessage und scheduler.postTask
  • Reale Benchmark-Ergebnisse zeigen, dass in Chrome und Firefox das 4-ms-Clamping greift, während MessageChannel und scheduler.postTask nahezu ohne Verzögerung arbeiten; Safari drosselt setTimeout noch stärker
  • Im Kern geht es um das Gleichgewicht zwischen dem Schutz der Nutzererfahrung und der Freiheit von Entwicklern; derzeit etabliert sich die Scheduler API als standardisierte Lösung, doch bei Missbrauch könnte eine neue Browser-Intervention eingeführt werden

Hintergrund der setTimeout-Beschränkung

  • Selbst bei setTimeout(0) erfolgt die tatsächliche Ausführung wegen Missbrauchs oft erst nach mindestens 4 ms
    const start = performance.now()  
    setTimeout(() => {  
      // wird nach etwa 4 ms ausgeführt  
      console.log(performance.now() - start)  
    }, 0)  
    
  • Damit sollen wahllose wiederholte Aufrufe verhindert und Akkuverbrauch sowie Render-Verzögerungen reduziert werden
  • Einige Browser verschärfen die Begrenzung je nach Umgebung
    • Akkubetrieb: im alten Edge 16 ms
    • Hintergrund-Tab: in Chrome Verzögerung von bis zu 1 Sekunde

Entstehung anderer Timer-APIs

  • setImmediate: nur in IE und altem Edge unterstützt, faktisch eingestellt
  • MessageChannel.postMessage: überträgt Aufgaben über einen separaten Kanal an den Event Loop
  • window.postMessage: gute Performance, aber Risiko von Kollisionen mit anderen Skripten
  • scheduler.postTask: in modernen Browsern unterstützt und als stabilste Option bewertet

Benchmark-Ergebnisse (MacBook Pro 2021, 101 Wiederholungen)

  • Chrome 139: setTimeout 4.2 ms, scheduler.postTask 0 ms
  • Firefox 142: setTimeout 4.72 ms, scheduler.postTask 0.01 ms
  • Safari 18.4: setTimeout 26.73 ms, MessageChannel 0.52 ms, window.postMessage 0.05 ms

Fallbeispiel fake-indexeddb

  • IndexedDB möchte Transaktionen direkt nach dem Ende der Mikrotasks des Event Loops automatisch committen
  • setImmediate in Node.js ist dafür ideal, aber im Browser ist setTimeout ineffizient
  • Ein Vorgang, der in Chrome 300 ms dauert, dehnt sich im Browser auf bis zu 4,8 Sekunden aus
  • Als Lösung wird standardmäßig scheduler.postTask verwendet und aus Kompatibilitätsgründen MessageChannel/window.postMessage als Fallback übernommen

Debatte um Browser-Interventionen

  • Eine Seite argumentiert, Timer müssten begrenzt werden, damit Entwickler vor sich selbst geschützt werden
  • Die andere Seite fordert, Freiheit zu gewährleisten, damit Entwickler selbst messen und optimieren können
  • Letztlich greifen Browser nach dem Prinzip „Nutzer zuerst“ ein, um Missbrauch zu verhindern
  • Die Scheduler API versucht beide Positionen zu vereinen, indem sie Entwicklern eine feinere Kontrolle über Aufgaben gibt und zugleich auf die Rendering-Pipeline des Browsers abgestimmt ist

Ausblick

  • postTask und postMessage werden vermutlich vorerst ohne Drosselung bestehen bleiben
  • Werden jedoch hohe Prioritäten wie user-blocking missbraucht, sind erneute Eingriffe möglich
  • Langfristig könnte eine weitere alternative API wie scheduler2 nötig werden

Noch keine Kommentare.

Noch keine Kommentare.