So geben Sie den Main-Thread frei

Geben Sie den Main-Thread frei, um die Reaktionsfähigkeit der Seite zu verbessern

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-02-07

Geben Sie den Main-Thread frei

Stellen Sie sich einen romantischen Film vor. Der Schauplatz ist ein kleiner französischer Marktplatz im Zentrum eines kleinen Dorfes. Die Straßen sind voller Paare, die Kaffee trinken, Croissants essen und Blumen kaufen. Stellen Sie sich nun vor, was passiert, wenn nur 1 Verkäufer gleichzeitig etwas von einem Verkäufer kaufen kann, während alle anderen warten müssen, bis sie an der Reihe sind. Der Bäcker wird mit Anfragen überhäuft, beim Floristen brechen Streitigkeiten aus und der romantische Spaziergang wird zu einer frustrierenden Wartezeit.

Nun ...  das ist so ziemlich das, was auf einer Website passiert, wenn es zu voll wird.

Die Bedeutung des Yieldings

Der Main-Thread eines Browsers erledigt alle wichtigen Prozesse und plant alle wichtigen Aufgaben (Parsen von HTML und CSS, Ausführen von JavaScript-Code, Behandlung von Eingabeereignissen wie Klicks und Scrollen und visuelles Rendering). 

Der Main-Thread eines Browsers läuft auf einem Single-Threaded-Modell. Das bedeutet, dass er nur eine Aufgabe gleichzeitig ausführen kann. Wenn eine Aufgabe (normalerweise JavaScript-Ausführung oder Rendering) zu laufen beginnt, führt der Browser diese Aufgabe 'bis zum Abschluss' aus und hört nicht auf, bis sie erledigt ist. Dies bedeutet, dass er keine andere Aufgabe planen oder ausführen wird, bis die vorherige Aufgabe fertig ist. Dies wird als 'Blockieren des Main-Threads' bezeichnet. Das Blockieren des Main-Threads ist ein Problem, wenn Besucher mit einer Seite interagieren, da die Seite während der Blockierzeit nicht reagiert. 

Eine Möglichkeit, das Blockieren des Main-Threads zu beheben, ist das 'Yielding an den Main-Thread'. Yielding ist eine Technik, bei der lange Aufgaben in mehrere kleinere Aufgaben aufgeteilt werden, damit der Main-Thread wichtigere Aufgaben (wie Benutzereingaben) erledigen kann. 

Lange Aufgaben und Blockierzeitraum: Wenn eine Aufgabe länger als 50 Millisekunden dauert, wird sie als lange Aufgabe klassifiziert, und alles, was über diese 50-Millisekunden-Schwelle hinausgeht, wird als 'Blockierzeitraum' der Aufgabe bezeichnet. Das Aufteilen dieser langen Aufgaben in kleinere Stücke ermöglicht es dem Browser, reaktionsfähig zu bleiben, selbst wenn rechenintensive Operationen durchgeführt werden.

Alte Yielding-Strategien

Vor der neuen Prioritized Task Scheduling API gab es 4 Wege, um an den Main-Thread zu yeilden. Alle haben ihre Einschränkungen und Bedenken!

  • setTimeout(): Die häufigste Strategie, setTimeout(), funktioniert, indem Code in einer Callback-Funktion nach einer festgelegten Verzögerung ausgeführt wird. Durch Festlegen einer Verzögerung (oder Timeout) von 0 fügt setTimeout() die Aufgabe an das Ende der Warteschlange an, sodass andere Aufgaben zuerst ausgeführt werden können. Ein großes Problem ist, dass setTimeout() nicht für präzises Scheduling ausgelegt ist, da Aufgaben nur an das Ende der Warteschlange geschoben werden können.
  • requestAnimationFrame(): requestAnimationFrame() funktioniert, indem eine Funktion in die Warteschlange gestellt wird, die vor dem nächsten Repaint des Browsers ausgeführt werden soll. requestAnimationFrame() wird oft mit setTimeout() kombiniert, um sicherzustellen, dass Callback-Funktionen nach dem nächsten Layout-Update geplant werden.
  • requestIdleCallback(): Diese Methode eignet sich am besten für unkritische Aufgaben mit niedriger Priorität, die während der Leerlaufzeit eines Browsers ausgeführt werden können. Während es hilft, den Main-Thread für wichtigere Aufgaben frei zu halten, leidet requestIdleCallback() unter einer erheblichen Einschränkung: Es gibt keine Garantie, dass die geplanten Aufgaben zeitnah (oder überhaupt!!!) ausgeführt werden, insbesondere bei einem ausgelasteten Main-Thread.
  • isInputPending(): isInputPending() funktioniert, indem auf ausstehende Benutzereingaben geprüft wird und nur dann ge-yielded wird, wenn eine Eingabe erkannt wird. isInputPending() kann zusammen mit anderen Yielding-Funktionen verwendet werden, um unnötiges Yielding zu verhindern. Leider kann es falsch negative Ergebnisse liefern und adressiert nicht die Notwendigkeit, für andere leistungskritische Aufgaben wie Animationen zu yielden.

Einführung: scheduler.yield()

Die Einschränkungen dieser 4 Methoden waren ein Anliegen für das Chrome-Team, insbesondere da viele Websites die Interaction to Next Paint Metrik nicht bestehen. Um dies zu beheben und zu helfen, hat das Chrome-Team eine neue API entwickelt, die eine granulare Kontrolle über das JavaScript-Scheduling gibt.

Treffen Sie scheduler.yield()! Mit window.scheduler.yield() können Entwickler effektiv sofort an den Main-Thread yielden, ohne die Reihenfolge der Aufgaben neu zu ordnen oder zusätzliche Komplexität zu schaffen.

Verwenden Sie Scheduler.yield() effektiv

Lassen Sie uns in den Code eintauchen und erforschen, wie man scheduler.yield() so nutzt, wie es gedacht ist! Bevor wir anfangen, scheduler.yield() zu verwenden, ist es wichtig, die Browserkompatibilität zu überprüfen, da es sich um eine experimentelle Funktion handelt und nicht alle Browser sie noch unterstützen. 

Beispielcode

function yieldToMain() {
  if ('scheduler' in window && 'yield' in window.scheduler) {
    return window.scheduler.yield();
  }
  return new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
}

Die yieldToMain() Funktion ist der Kern der Übergabe der Kontrolle an den Main-Thread. Sie prüft zuerst, ob sowohl window.scheduler als auch window.scheduler.yield existieren. Wenn ja, können wir window.scheduler.yield sicher verwenden. Wenn window.scheduler.yield nicht unterstützt wird, fällt der Code auf setTimeout zurück.

Kürzere und produktionsreife Version

Oder verwenden Sie diese kürzere, produktionsreife Version, die den ternären Operator verwendet:

/* oder kürzer und produktionsreif: */
function yieldToMain(){
  return"scheduler"in window&&"yield"in window.scheduler?
  window.scheduler.yield():new Promise(e=>{setTimeout(e,0)})
}

Beispiel aus dem wirklichen Leben: Verbesserung der Suche mit yieldToMain():

Lassen Sie uns sehen, wie wir yieldToMain() verwenden können, um das Sucherlebnis für Ihre Benutzer zu verbessern:

Die handleSearch() Funktion demonstriert, wie yieldToMain() effektiv verwendet werden kann. Sie aktualisiert zuerst den Button-Inhalt, um sofortiges Feedback zu geben, dass eine Suche im Gange ist. Sie können yieldToMain() hier verwenden, um dem Browser zu erlauben, das Layout zu aktualisieren.

Als nächstes ruft fetchData() Suchdaten ab und updateHTML(data) zeigt die Ergebnisse an. Ein weiteres  yieldToMain() sorgt für ein schnelles Layout-Update (da wir nie sicher sein können, dass nicht andere Event-Listener nach dieser Aufgabe warten).  Schließlich werden andere, weniger wichtige Aufgaben während der Leerlaufzeit des Browsers geplant. Beachten Sie, dass ich hier nicht an den Main-Thread ge-yielded habe, da requestIdleCallback() nur ausgeführt wird, wenn der Main-Thread im Leerlauf ist.

async function handleSeach(){
 /* Button-Inhalt nach dem Absenden schnell aktualisieren*/
 updateButtontoPending();

 /* Yield to Main */
 await yieldToMain();

 /* Daten abrufen und HTML aktualisieren*/
 const data = await fetchData();
 updateHTML(data);

 /* Yield to Main erneut */
 await yieldToMain();

 /* manche Funktion sollte nur während der Browser-Leerlaufzeit laufen*/
 requestIdleCallback(sendDataToAnalytics);
}

Warum schedulier.yield() einfach besser ist

Im Gegensatz zu setTimeout(), das verzögerte Aufgaben an das Ende der Aufgabenwarteschlange anfügt, pausiert scheduler.yield() nur die Javascript-Warteschlange und pausierte Aufgaben bleiben am Anfang der Warteschlange, wodurch sichergestellt wird, dass sie so schnell wie möglich ausgeführt werden, nachdem Aufgaben mit höherer Priorität (wie die Behandlung von Eingabe-Callbacks) abgeschlossen wurden. Dieses "Front-of-Queue"-Verhalten adressiert das größte Problem der alten Yielding-Methoden. Und Entwickler können jetzt 'an den Main-Thread yielden', ohne das Risiko einzugehen, dass ihre wichtigen Aufgaben durch andere weniger wichtige Aufgaben verzögert werden.

yielding timeline

Ein weiterer Vorteil von scheduler.yield() ist, dass es so konzipiert ist, mit der Prioritized Task Scheduling API wie scheduler.postTask() zusammenzuarbeiten, was die Priorisierung von Aufgaben basierend auf ihrer Wichtigkeit ermöglicht. Diese Kombination von Funktionen bietet Entwicklern ein leistungsstarkes Toolkit zur Optimierung ihrer Webanwendungen für Reaktionsfähigkeit und Leistung.


So geben Sie den Main-Thread freiCore Web Vitals So geben Sie den Main-Thread frei