Signatur
Beschreibung
FileSystemChangeRecord ist ein Wörterbuch (Dictionary) der File System API. Man erzeugt es nie selbst: Der Browser übergibt ein Array solcher Einträge an die Callback-Funktion eines FileSystemObserver, sobald sich in einem beobachteten Bereich etwas ändert. Das kann das Origin Private File System (OPFS) sein oder ein Ordner bzw. eine Datei, den der Nutzer über showDirectoryPicker() bzw. showOpenFilePicker() freigegeben hat.
Jeder Eintrag sagt, was passiert ist (type), wo es passiert ist (changedHandle und relativePathComponents) und welche Beobachtung den Eintrag ausgelöst hat (root). Bei Verschiebungen oder Umbenennungen steht in relativePathMovedFrom zusätzlich der alte Pfad.
Typische Einsatzfälle sind Editoren und IDEs im Browser, die einen Projektordner synchron halten, Dateimanager, Werkzeuge mit automatischem Neuladen oder Synchronisierung zwischen Tabs oder Workern, die in dasselbe OPFS schreiben. Statt regelmäßig nachzufragen (Polling), wird die Anwendung gezielt benachrichtigt.
Mögliche Werte von type: "appeared" (neu angelegt oder hinzugekommen), "disappeared" (gelöscht), "modified" (Inhalt geändert), "moved" (verschoben oder umbenannt), "unknown" (Änderungen sind möglicherweise verloren gegangen, man sollte neu einlesen) und "errored" (die Beobachtung ist fehlgeschlagen und endet).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $changedHandle Pflicht | FileSystemFileHandle | FileSystemDirectoryHandle | FileSystemSyncAccessHandle | null | Handle der geänderten Datei oder des geänderten Verzeichnisses. Im OPFS kann es auch ein FileSystemSyncAccessHandle sein. Bei "disappeared", "unknown" oder "errored" verweist es unter Umständen auf ein Element, das nicht mehr existiert. |
|
| $relativePathComponents Pflicht | string[] | Pfad der Änderung relativ zu root, als Array von Namen, z. B. ["src", "main.js"]. Ist der Wert leer, betrifft die Änderung root selbst. |
|
| $relativePathMovedFrom Pflicht | string[] | null | null | Nur bei type === "moved" belegt: der frühere Pfad relativ zu root. Sonst null. |
| $root Pflicht | FileSystemFileHandle | FileSystemDirectoryHandle | FileSystemSyncAccessHandle | Das Handle, das an observer.observe() übergeben wurde. Damit lässt sich unterscheiden, welche von mehreren Beobachtungen den Eintrag ausgelöst hat. |
|
| $type Pflicht | "appeared" | "disappeared" | "modified" | "moved" | "unknown" | "errored" | Art der Änderung (siehe Beschreibung). |
Rückgabewert
records-Arrays an den Callback von FileSystemObserver übergeben.Beispiele
Einträge im OPFS protokollieren
const root = await navigator.storage.getDirectory();
const observer = new FileSystemObserver((records, obs) => {
for (const record of records) {
const pfad = record.relativePathComponents.join('/') || '(root)';
console.log(`${record.type}: ${pfad}`);
}
});
await observer.observe(root, { recursive: true });
// Änderung auslösen
const datei = await root.getFileHandle('notizen.txt', { create: true });
const writable = await datei.createWritable();
await writable.write('Hallo');
await writable.close();
Umbenennungen und Verschiebungen auswerten
const handleRecord = (record) => {
const pfad = record.relativePathComponents.join('/');
switch (record.type) {
case 'moved': {
const alt = record.relativePathMovedFrom?.join('/') ?? '?';
console.log(`Verschoben: ${alt} → ${pfad}`);
break;
}
case 'disappeared':
console.log(`Gelöscht: ${pfad}`);
break;
case 'appeared':
case 'modified':
console.log(`${record.type}: ${pfad} (${record.changedHandle?.kind})`);
break;
}
};
const observer = new FileSystemObserver((records) => records.forEach(handleRecord));
const dir = await navigator.storage.getDirectory();
await observer.observe(dir, { recursive: true });
const f = await dir.getFileHandle('entwurf.md', { create: true });
await f.move('final.md');
Projektordner eines Editors synchron halten (inkl. unknown/errored)
const button = document.querySelector('#ordner-oeffnen');
button.addEventListener('click', async () => {
const projekt = await window.showDirectoryPicker();
const neuEinlesen = async () => {
const namen = [];
for await (const [name] of projekt.entries()) namen.push(name);
console.log('Dateiliste aktualisiert:', namen);
};
const observer = new FileSystemObserver(async (records, obs) => {
for (const record of records) {
if (record.type === 'errored') {
console.warn('Beobachtung beendet für', record.root.name);
obs.disconnect();
return;
}
if (record.type === 'unknown') {
// Änderungen sind evtl. verloren gegangen – komplett neu einlesen
await neuEinlesen();
return;
}
}
await neuEinlesen();
});
await observer.observe(projekt, { recursive: true });
await neuEinlesen();
});
// Wichtig · Fallstricke
- Experimentell:
FileSystemObserverund damitFileSystemChangeRecordgibt es bisher nur in Chromium-Browsern (Chrome/Edge ab etwa Version 133). Firefox und Safari unterstützen sie nicht. Vor der Nutzung prüfen:if ('FileSystemObserver' in self) { … }. - Die Reihenfolge und Zusammenfassung der Einträge ist nicht garantiert. Ein Speichervorgang kann mehrere
"modified"-Einträge erzeugen, eine Umbenennung auf manchen Plattformen als"disappeared"und anschließend"appeared"erscheinen statt als"moved". - Bei
"unknown"sollte man den Zustand vollständig neu einlesen, statt sich auf einzelne Einträge zu verlassen. - Nach
"errored"kommen für diese Beobachtung keine Meldungen mehr, sie muss mitobserve()neu gestartet werden, z. B. wenn der Nutzer die Berechtigung entzogen hat. changedHandlekann auf eine gelöschte Datei zeigen. Zugriffe wiegetFile()werfen dann einenNotFoundErrorund sollten mittry/catchabgesichert werden.- Nur in sicheren Kontexten (HTTPS) verfügbar. Außerhalb des OPFS ist zusätzlich eine Lese-Berechtigung für das beobachtete Handle nötig.