Signatur
Beschreibung
timeRemaining() wird auf dem IdleDeadline-Objekt aufgerufen, das der Browser einem mit requestIdleCallback() registrierten Callback übergibt. Die Methode gibt einen DOMHighResTimeStamp zurück. Das ist eine Gleitkommazahl in Millisekunden und gibt an, wie viel Zeit bis zum Ende des aktuellen Leerlaufzeitraums noch übrig ist.
Gedacht ist die Methode für kooperatives Scheduling: Man teilt unwichtige Arbeit in kleine Einheiten auf (Analytics senden, Daten vorberechnen, Caches aufwärmen, Listen vorrendern) und arbeitet diese in einer Schleife ab, solange timeRemaining() einen ausreichend großen Wert liefert. Ist die Zeit aufgebraucht, gibt man die Kontrolle an den Browser zurück und plant mit einem erneuten requestIdleCallback() den nächsten Durchlauf ein.
Der Wert ist höchstens 50 ms, damit der Browser bei einer Nutzereingabe innerhalb der Wahrnehmungsgrenze reagieren kann. Ist der Leerlaufzeitraum vorbei, oder wurde der Callback wegen eines abgelaufenen timeout aufgerufen, gibt die Methode 0 zurück. In diesem Fall zeigt deadline.didTimeout an, ob ein Timeout der Grund war.
Rückgabewert
0 und 50. Der Wert ist 0, wenn der Leerlaufzeitraum abgelaufen ist.Beispiele
Aufgaben-Warteschlange in Leerlaufzeiten abarbeiten
const tasks = Array.from({ length: 1000 }, (_, i) => () => Math.sqrt(i) * Math.random());
let processed = 0;
const work = (deadline) => {
// Weiterarbeiten, solange Zeit übrig ist oder ein Timeout erzwungen wurde
while ((deadline.timeRemaining() > 1 || deadline.didTimeout) && tasks.length > 0) {
tasks.shift()();
processed++;
}
if (tasks.length > 0) {
requestIdleCallback(work, { timeout: 2000 });
} else {
console.log(`Fertig: ${processed} Aufgaben verarbeitet`);
}
};
requestIdleCallback(work, { timeout: 2000 });
Verfügbare Leerlaufzeit protokollieren
requestIdleCallback((deadline) => {
const ms = deadline.timeRemaining();
console.log(`Verbleibend: ${ms.toFixed(2)} ms, Timeout: ${deadline.didTimeout}`);
});
Analytics-Events gebündelt im Leerlauf senden
const queue = [];
let scheduled = false;
const track = (event) => {
queue.push({ event, ts: Date.now() });
if (!scheduled) {
scheduled = true;
requestIdleCallback(flush, { timeout: 5000 });
}
};
const flush = (deadline) => {
const batch = [];
while (queue.length && (deadline.timeRemaining() > 2 || deadline.didTimeout)) {
batch.push(queue.shift());
}
if (batch.length) {
navigator.sendBeacon('/analytics', JSON.stringify(batch));
}
scheduled = queue.length > 0;
if (scheduled) requestIdleCallback(flush, { timeout: 5000 });
};
track('page_view');
track('button_click');
// Wichtig · Fallstricke
- Keine DOM-Änderungen im Idle-Callback: Layout-Änderungen können Reflows auslösen, die länger dauern als die verbleibende Zeit. DOM-Updates sollte man stattdessen mit
requestAnimationFrame()einplanen. - Den Wert bei jedem Schleifendurchlauf neu abfragen. Er ändert sich laufend und sollte nicht zwischengespeichert werden.
- Eine einzelne Arbeitseinheit sollte deutlich kürzer sein als die verbleibende Zeit. Sonst überschreitet man die Deadline trotz Prüfung.
- Wurde der Callback wegen eines
timeoutaufgerufen, lieferttimeRemaining()0. Deshalb zusätzlichdidTimeoutprüfen, sonst wird nie gearbeitet. - Der Rückgabewert kann aus Datenschutzgründen (Schutz vor Timing-Angriffen) mit geringerer Genauigkeit geliefert werden.
- Kompatibilität: Safari unterstützt
requestIdleCallback()nicht standardmäßig. Mit einer Feature-Erkennung ('requestIdleCallback' in window) prüfen und als Ersatz z. B.setTimeoutmit einem nachgebildeten Deadline-Objekt verwenden.