Start · Sprachen · JavaScript · Referenz · FileSystemSyncAccessHandle.flush()

FileSystemSyncAccessHandle.flush()

Methode

Schreibt alle über <code>write()</code> vorgenommenen, noch gepufferten Änderungen der verknüpften Datei im Origin Private File System dauerhaft auf den Datenträger.

seit JavaScript Baseline 2023: Chrome 102+, Edge 102+, Firefox 111 Kategorie: webapi

Signatur

FileSystemSyncAccessHandle.prototype.flush()

Beschreibung

flush() sorgt dafür, dass Daten, die mit FileSystemSyncAccessHandle.write() geschrieben wurden, tatsächlich dauerhaft gespeichert werden. Der Browser bzw. das Betriebssystem darf Schreibvorgänge zwischenpuffern; erst nach flush() ist sichergestellt, dass ein Absturz oder ein Schließen des Tabs die Änderungen nicht mehr verliert. Die Methode ist das Gegenstück zu fsync() in klassischen Dateisystem-APIs.

Die Methode steht ausschließlich im Origin Private File System (OPFS) und nur in dedizierten Web Workern zur Verfügung, da FileSystemSyncAccessHandle synchron arbeitet und den Haupt-Thread sonst blockieren würde. Ein Handle erhält man über FileSystemFileHandle.createSyncAccessHandle().

Typische Einsatzfälle sind Datenbank-Engines im Browser (z. B. SQLite über WebAssembly), Journal- oder Log-Dateien und jede Anwendung, die an definierten Punkten (Transaktionsende, Checkpoint) Datenkonsistenz garantieren muss. flush() ist vergleichsweise teuer – man ruft es daher gezielt nach einer Gruppe von Schreibvorgängen auf, nicht nach jedem einzelnen write().

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Die Methode arbeitet synchron und kehrt erst zurück, wenn die Daten gesichert sind. Hinweis: In älteren Chromium-Versionen (vor 108) lieferte sie ein Promise<undefined>.

Beispiele

Text in eine OPFS-Datei schreiben und sichern (im Worker)

// worker.js – läuft in einem dedizierten Web Worker
const saveNote = async (text) => {
  const root = await navigator.storage.getDirectory();
  const fileHandle = await root.getFileHandle('notiz.txt', { create: true });
  const access = await fileHandle.createSyncAccessHandle();

  try {
    const data = new TextEncoder().encode(text);
    access.truncate(0);                 // alten Inhalt verwerfen
    const written = access.write(data, { at: 0 });
    access.flush();                     // dauerhaft auf den Datenträger schreiben
    console.log(`${written} Bytes gesichert, Dateigröße: ${access.getSize()}`);
  } finally {
    access.close();                     // Sperre auf die Datei freigeben
  }
};

saveNote('Hallo OPFS!');
11 Bytes gesichert, Dateigröße: 11

Log-Einträge sammeln und gebündelt flushen

// worker.js
const encoder = new TextEncoder();
let access;
let pending = 0;

const openLog = async () => {
  const root = await navigator.storage.getDirectory();
  const handle = await root.getFileHandle('app.log', { create: true });
  access = await handle.createSyncAccessHandle();
};

const log = (message) => {
  const line = encoder.encode(`${new Date().toISOString()} ${message}\n`);
  access.write(line, { at: access.getSize() }); // anhängen
  pending++;
  // Nur alle 50 Einträge flushen – spart teure Datenträgerzugriffe
  if (pending >= 50) {
    access.flush();
    pending = 0;
  }
};

await openLog();
for (let i = 0; i < 120; i++) log(`Ereignis ${i}`);
access.flush(); // Rest sichern
access.close();
console.log('Log geschrieben');
Log geschrieben

Haupt-Thread steuert den Worker per postMessage

// main.js
const worker = new Worker('storage-worker.js');
worker.onmessage = ({ data }) => console.log('Worker:', data);
worker.postMessage({ file: 'daten.json', content: JSON.stringify({ id: 1 }) });

// storage-worker.js
self.onmessage = async ({ data: { file, content } }) => {
  const root = await navigator.storage.getDirectory();
  const fh = await root.getFileHandle(file, { create: true });
  const access = await fh.createSyncAccessHandle();
  try {
    access.truncate(0);
    access.write(new TextEncoder().encode(content), { at: 0 });
    access.flush();
    self.postMessage('gespeichert');
  } catch (err) {
    self.postMessage(`Fehler: ${err.name}`);
  } finally {
    access.close();
  }
};
Worker: gespeichert

// Wichtig · Fallstricke

  • Nur in dedizierten Web Workern: Im Haupt-Thread, in Shared Workern und in Service Workern gibt es createSyncAccessHandle() nicht.
  • InvalidStateError: Wird ausgelöst, wenn flush() nach close() aufgerufen wird.
  • Synchron statt asynchron: Chromium vor Version 108 lieferte ein Promise. Wer alte Versionen unterstützen muss, kann await access.flush() schreiben – bei einem synchronen Rückgabewert (undefined) schadet das nicht.
  • Performance: Jeder Aufruf erzwingt einen Datenträgerzugriff. Nach jedem kleinen write() zu flushen bremst stark; besser an Transaktions- oder Checkpoint-Grenzen flushen.
  • close() ersetzt flush() nicht zuverlässig: Beim Schließen werden die Daten zwar in der Regel gespeichert, für garantierte Dauerhaftigkeit an definierten Punkten sollte man aber ausdrücklich flush() aufrufen.
  • Das Handle sperrt die Datei exklusiv; solange es offen ist, schlagen weitere createSyncAccessHandle()- oder createWritable()-Aufrufe auf dieselbe Datei fehl (NoModificationAllowedError).
  • Setzt einen sicheren Kontext (HTTPS) voraus.