Signatur
Beschreibung
Die Methode isInputPending() wird über navigator.scheduling aufgerufen. Sie gibt true zurück, wenn der Benutzer mit der Seite interagiert, diese Eingabe aber noch nicht verarbeitet wurde. Das ist zum Beispiel der Fall, wenn gerade eine lange Aufgabe auf dem Hauptthread läuft. So muss man lange Rechenschleifen nicht in festen Abständen „auf Verdacht“ unterbrechen. Man gibt nur dann an die Ereignisschleife ab, wenn tatsächlich eine Eingabe wartet.
Das typische Muster sieht so aus: Man arbeitet eine Aufgabenliste in einer Schleife ab und prüft zwischendurch isInputPending(). Liefert die Methode true, unterbricht man die Arbeit, zum Beispiel mit setTimeout, scheduler.yield() oder MessageChannel. Der Browser kann die Eingabe dann sofort verarbeiten. Das verbessert die Reaktionsfähigkeit der Seite, messbar etwa an der Kennzahl Interaction to Next Paint (INP), ohne den Durchsatz unnötig zu senken.
Standardmäßig werden nur diskrete Ereignisse berücksichtigt, etwa keydown, mousedown oder click. Mit der Option includeContinuous: true zählen auch kontinuierliche Ereignisse wie mousemove, pointermove oder wheel. Diese treten sehr häufig auf und führen daher öfter zu true.
Rückgabewert
true, wenn ein passendes Eingabeereignis auf Verarbeitung wartet, sonst false.Beispiele
Lange Aufgabenliste reaktionsfreundlich abarbeiten
const yieldToMain = () => new Promise((resolve) => setTimeout(resolve, 0));
const processTasks = async (tasks) => {
let pauses = 0;
while (tasks.length > 0) {
// Nur unterbrechen, wenn der Benutzer wirklich etwas eingibt
if (navigator.scheduling?.isInputPending()) {
pauses++;
await yieldToMain();
continue;
}
const task = tasks.shift();
task();
}
console.log(`Fertig, ${pauses} Mal an den Browser abgegeben`);
};
const tasks = Array.from({ length: 10000 }, (_, i) => () => Math.sqrt(i) * Math.random());
processTasks(tasks);
Feature-Erkennung mit Zeitbudget als Fallback
const hasInputPending = typeof navigator.scheduling?.isInputPending === 'function';
const BUDGET_MS = 50;
const shouldYield = (startTime) => {
// Zeitbudget ist in jedem Browser eine harte Obergrenze
if (performance.now() - startTime > BUDGET_MS) return true;
return hasInputPending ? navigator.scheduling.isInputPending() : false;
};
const runChunked = async (items, handle) => {
let start = performance.now();
for (const item of items) {
if (shouldYield(start)) {
await new Promise((r) => setTimeout(r, 0));
start = performance.now();
}
handle(item);
}
};
console.log('isInputPending verfügbar:', hasInputPending);
runChunked([...Array(5000).keys()], (n) => n * n);
Kontinuierliche Ereignisse einbeziehen
// z. B. während Drag-&-Drop auch auf Mausbewegungen reagieren
const renderHeavyFrame = () => {
const start = performance.now();
while (performance.now() - start < 100) {
if (navigator.scheduling?.isInputPending({ includeContinuous: true })) {
console.log('Eingabe (inkl. mousemove) wartet, breche ab');
return false;
}
}
return true;
};
document.addEventListener('pointerdown', () => {
requestAnimationFrame(() => console.log('Frame komplett:', renderHeavyFrame()));
});
// Wichtig · Fallstricke
- Kompatibilität: Die Methode ist experimentell und nur in Chromium-Browsern verfügbar (ab Version 87). Firefox und Safari unterstützen sie nicht. Prüfen Sie immer vorher mit
navigator.scheduling?.isInputPending, ob sie existiert. Das Chrome-Team empfiehlt inzwischen eherscheduler.yield()bzw. regelmäßiges Abgeben nach einem festen Zeitbudget. - Nicht als einziges Kriterium verwenden: Auch ohne Eingabe muss der Browser rendern, Timer, Netzwerkantworten und
requestAnimationFrameabarbeiten. Deshalb sollte man zusätzlich ein Zeitbudget einhalten, z. B. maximal 50 ms pro Aufgabe. - Falsch-negative Ergebnisse: Die Methode kann
falseliefern, obwohl eine Eingabe wartet. Das passiert etwa bei Eingaben, die noch nicht beim Renderer angekommen sind, oder bei Eingaben für ursprungsfremde iframes. Aus Datenschutzgründen werden nur Eingaben gemeldet, die an Dokumente desselben Ursprungs gehen. - Nur Hauptthread: Ein Aufruf in einem Worker ist nicht sinnvoll, weil dort
navigator.schedulingnicht verfügbar ist. includeContinuous: trueliefert sehr häufigtrue. Das kann zu übermäßig vielen Unterbrechungen und damit zu geringem Durchsatz führen.