Signatur
Beschreibung
Ein PerformanceObserver sammelt neue Performance-Einträge in einer internen Puffer-Liste und übergibt sie asynchron gebündelt an seinen Callback. Mit takeRecords() holst du diese wartenden Einträge synchron sofort ab. Die Puffer-Liste ist danach leer, und der Callback wird für genau diese Einträge nicht mehr aufgerufen.
Gebraucht wird das vor allem kurz vor dem Beenden der Beobachtung mit disconnect() oder beim Verlassen der Seite (visibilitychange, pagehide). Dort würde ein noch ausstehender Callback nicht mehr laufen. Ohne takeRecords() gingen also die zuletzt aufgezeichneten Messwerte verloren, etwa der finale Wert für Largest Contentful Paint oder die letzten Layout-Shift-Einträge.
Die Methode liefert ein ganz normales Array (keine PerformanceObserverEntryList). Darauf funktionieren forEach, filter, map usw. direkt. Ein zweiter Aufruf direkt danach ergibt ein leeres Array.
Rückgabewert
PerformanceEntry-Objekte, die der Observer bisher gepuffert, aber noch nicht an den Callback übergeben hat. Wartet nichts, ist das Array leer.Beispiele
Wartende Einträge vor disconnect() abholen
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.log('Callback:', entry.name, entry.duration);
});
});
observer.observe({ entryTypes: ['mark', 'measure'] });
performance.mark('start');
// ... Arbeit ...
performance.mark('ende');
performance.measure('arbeit', 'start', 'ende');
// Synchron abholen, bevor der asynchrone Callback feuert
const records = observer.takeRecords();
console.log(records.map((e) => `${e.entryType}:${e.name}`));
observer.disconnect();
Letzten LCP-Wert beim Verlassen der Seite senden
let lcp = 0;
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
lcp = entries.at(-1).startTime;
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
document.addEventListener('visibilitychange', () => {
if (document.visibilityState !== 'hidden') return;
// Noch nicht zugestellte Einträge sichern
const pending = observer.takeRecords();
if (pending.length) lcp = pending.at(-1).startTime;
observer.disconnect();
navigator.sendBeacon('/analytics', JSON.stringify({ lcp: Math.round(lcp) }));
}, { once: true });
Zweiter Aufruf liefert ein leeres Array
const observer = new PerformanceObserver(() => {});
observer.observe({ type: 'mark' });
performance.mark('a');
performance.mark('b');
console.log(observer.takeRecords().length);
console.log(observer.takeRecords().length);
// Wichtig · Fallstricke
- Einträge werden entfernt: Was
takeRecords()zurückgibt, erreicht den Callback nicht mehr. Wenn du die Einträge dort auswertest, musst du sie selbst mit derselben Logik weiterverarbeiten. Sonst gehen Messwerte verloren. - Nicht verwechseln mit
performance.getEntries():takeRecords()liefert nur die Einträge, die im Puffer des Observers noch auf Zustellung warten.performance.getEntries()dagegen liest die globale Performance-Timeline aus. disconnect()verwirft wartende Einträge: RufetakeRecords()deshalb vordisconnect()auf.- Beim Entladen der Seite: Nutze
visibilitychangeoderpagehidestattunload.unloadist unzuverlässig und verhindert den Back/Forward-Cache. - Kompatibilität: In allen modernen Browsern verfügbar, ebenso in Web Workern. Ältere Safari-Versionen (unter 11) kennen die Methode nicht. Prüfe notfalls mit
typeof observer.takeRecords === 'function'. Ob ein Browser einen Eintragstyp unterstützt, zeigtPerformanceObserver.supportedEntryTypes.