Start · Sprachen · JavaScript · Referenz · FileSystemFileHandle.createSyncAccessHandle()

FileSystemFileHandle.createSyncAccessHandle()

Methode

Gibt ein <code>Promise</code> zurück, das mit einem <code>FileSystemSyncAccessHandle</code> erfüllt wird. Damit liest und schreibt man eine OPFS-Datei synchron in einem Web Worker.

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

Signatur

FileSystemFileHandle.prototype.createSyncAccessHandle(options)

Beschreibung

Die Methode createSyncAccessHandle() des Interfaces FileSystemFileHandle öffnet eine Datei im Origin Private File System (OPFS) für synchronen Zugriff mit hoher Leistung. Das zurückgegebene FileSystemSyncAccessHandle hat die Methoden read(), write(), truncate(), getSize(), flush() und close(). Sie arbeiten synchron und direkt auf der Datei. Dabei entsteht keine temporäre Kopie wie bei createWritable().

Die API ist für rechenintensive Fälle gedacht, bei denen viele kleine Lese- und Schreibzugriffe an beliebigen Stellen der Datei nötig sind. Typische Beispiele sind SQLite über WebAssembly, Datenbank-Engines, Video- oder Bildbearbeitung und Emulatoren. Weil synchrone Ein- und Ausgabe den Hauptthread blockieren würde, gibt es die Methode ausschließlich in dedizierten Web Workern. Im Hauptthread, in Shared Workern und in Service Workern ist sie nicht verfügbar.

Standardmäßig (mode: "readwrite") setzt die Methode eine exklusive Sperre auf die Datei. Solange das Handle offen ist, kann kein anderes Sync-Handle und kein FileSystemWritableFileStream für dieselbe Datei erzeugt werden. Deshalb muss man das Handle nach getaner Arbeit unbedingt mit close() schließen. Mit den Modi "read-only" und "readwrite-unsafe" können mehrere Handles gleichzeitig offen sein.

Parameter

Name Typ Default Beschreibung
$options object {} Optionales Konfigurationsobjekt.
$options.mode "readwrite" | "read-only" | "readwrite-unsafe" "readwrite" Sperrmodus. "readwrite": Lesen und Schreiben mit exklusiver Sperre. "read-only": nur Lesen, mehrere Handles gleichzeitig möglich, write() und truncate() werfen einen Fehler. "readwrite-unsafe": Lesen und Schreiben ohne exklusive Sperre, mehrere gleichzeitige Schreiber möglich, die Synchronisierung liegt beim Entwickler. Die Option mode gibt es derzeit nur in Chromium (ab Version 121).

Rückgabewert

Typ
Promise<FileSystemSyncAccessHandle>
Beschreibung
Ein Promise, das mit einem FileSystemSyncAccessHandle für synchronen Dateizugriff erfüllt wird. Es wird abgelehnt mit NotAllowedError (Berechtigung fehlt oder die Datei liegt nicht im OPFS), InvalidStateError (das Handle gehört nicht zum OPFS), NotFoundError (die Datei existiert nicht mehr) oder NoModificationAllowedError (die Sperre ist nicht zu bekommen, weil schon ein anderes Handle offen ist).

Beispiele

Text in eine OPFS-Datei schreiben und zurücklesen (worker.js)

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

  try {
    const encoder = new TextEncoder();
    const bytes = encoder.encode(data);

    // Datei leeren und ab Position 0 schreiben
    access.truncate(0);
    access.write(bytes, { at: 0 });
    access.flush();

    // Gesamte Datei wieder einlesen
    const size = access.getSize();
    const buffer = new Uint8Array(size);
    access.read(buffer, { at: 0 });

    self.postMessage(new TextDecoder().decode(buffer));
  } finally {
    access.close(); // Sperre unbedingt freigeben!
  }
};

Worker aus dem Hauptthread starten

// main.js
const worker = new Worker('worker.js');

worker.onmessage = ({ data }) => {
  console.log('Vom Worker gelesen:', data);
};

worker.postMessage('Hallo OPFS!');
Vom Worker gelesen: Hallo OPFS!

Daten an die Datei anhängen (Log-Datei)

// worker.js
const appendLog = async (line) => {
  const root = await navigator.storage.getDirectory();
  const handle = await root.getFileHandle('app.log', { create: true });
  const access = await handle.createSyncAccessHandle();
  try {
    const bytes = new TextEncoder().encode(`${new Date().toISOString()} ${line}\n`);
    // Am aktuellen Dateiende anhängen
    const written = access.write(bytes, { at: access.getSize() });
    access.flush();
    return written;
  } finally {
    access.close();
  }
};

appendLog('Worker gestartet').then((n) => console.log(`${n} Bytes geschrieben`));
34 Bytes geschrieben

Mehrere gleichzeitige Leser mit mode: "read-only" (Chromium)

// worker.js – Chromium 121+
const root = await navigator.storage.getDirectory();
const handle = await root.getFileHandle('daten.bin', { create: true });

// Ohne mode würde der zweite Aufruf mit NoModificationAllowedError fehlschlagen
const readerA = await handle.createSyncAccessHandle({ mode: 'read-only' });
const readerB = await handle.createSyncAccessHandle({ mode: 'read-only' });

console.log(readerA.getSize() === readerB.getSize());

readerA.close();
readerB.close();
true

// Wichtig · Fallstricke

  • Nur in dedizierten Workern: Im Hauptthread ist createSyncAccessHandle undefined. Vorher mit 'createSyncAccessHandle' in FileSystemFileHandle.prototype prüfen.
  • Nur OPFS: Die Methode funktioniert nur mit Handles aus navigator.storage.getDirectory(). Bei Dateien, die per showOpenFilePicker() gewählt wurden, wird das Promise abgelehnt.
  • Exklusive Sperre: Im Standardmodus blockiert ein offenes Handle alle weiteren Zugriffe auf die Datei, auch aus anderen Tabs. Deshalb immer close() in einem finally-Block aufrufen, sonst bleibt die Datei bis zum Beenden des Workers gesperrt.
  • Ältere Safari-Versionen (vor 16.4) haben getSize(), truncate(), flush() und close() asynchron umgesetzt, also mit Promise als Rückgabewert. Für breite Kompatibilität kann man deren Ergebnis mit await abwarten. Bei synchronen Rückgabewerten schadet das nicht.
  • Die Option mode gibt es derzeit nur in Chromium (ab 121). Firefox und Safari ignorieren sie und verwenden immer "readwrite".
  • read() und write() erwarten ein ArrayBuffer, eine TypedArray oder eine DataView. Strings muss man vorher mit TextEncoder umwandeln.
  • Das OPFS unterliegt der Speicherquote des Browsers. Nutzer können die Daten beim Löschen der Website-Daten entfernen. Mit navigator.storage.persist() lässt sich dauerhafter Speicher anfordern.