Hochleistungsspeicher für Ihre Anwendung: die Storage Foundation API

Die Webplattform bietet Entwicklern zunehmend die Tools, die sie benötigen, um optimierte, leistungsstarke Anwendungen für das Web zu erstellen. Vor allem hat WebAssembly (Wasm) die Tür zu schnellen und leistungsstarken Webanwendungen geöffnet. Technologien wie Emscripten ermöglichen es Entwicklern jetzt, bewährten Code im Web wiederzuverwenden. Um dieses Potenzial wirklich zu nutzen, müssen Entwickler die gleiche Leistung und Flexibilität in Bezug auf Speicher haben.

Hier kommt die Storage Foundation API ins Spiel. Die Storage Foundation API ist eine neue schnelle und unüberlegte Storage API, mit der sich neue und häufig angefragte Anwendungsfälle für das Web erschließen lassen, z. B. die Implementierung leistungsstarker Datenbanken und die reibungslose Verwaltung großer temporärer Dateien. Mit dieser neuen Benutzeroberfläche können Entwickler ihren eigenen Speicher ins Web mitnehmen und so die Funktionslücke zwischen web- und plattformspezifischem Code verringern.

Die Storage Foundation API ähnelt einem sehr einfachen Dateisystem und bietet Entwicklern Flexibilität, da sie generische, einfache und leistungsfähige Primitiven zur Verfügung stellt, auf denen sie übergeordnete Komponenten erstellen können. Anwendungen können das für ihre Anforderungen am besten geeignete Tool nutzen und die richtige Balance zwischen Nutzerfreundlichkeit, Leistung und Zuverlässigkeit finden.

Warum braucht das Web eine weitere Storage-API?

Die Webplattform bietet Entwicklern eine Reihe von Speicheroptionen, die alle auf bestimmte Anwendungsfälle zugeschnitten sind.

  • Einige dieser Optionen überschneiden sich eindeutig nicht mit diesem Vorschlag, da nur sehr kleine Datenmengen wie Cookies oder die Web Storage API gespeichert werden können, die aus den Mechanismen sessionStorage und localStorage besteht.
  • Andere Optionen wie die File and Directory Entries API oder WebSQL wurden bereits aus verschiedenen Gründen eingestellt.
  • Die File System Access API hat eine ähnliche API-Oberfläche, verwendet jedoch eine Schnittstelle zum Dateisystem des Clients und ermöglicht den Zugriff auf Daten, die sich möglicherweise außerhalb des Ursprungs- oder sogar des Browsers befinden. Dieser andere Fokus erfordert strengere Sicherheitsaspekte und höhere Leistungskosten.
  • Die IndexedDB API kann als Back-End für einige Anwendungsfälle der Storage Foundation API verwendet werden. Emscripten enthält beispielsweise IDBFS, ein IndexedDB-basiertes nichtflüchtiges Dateisystem. Da IndexedDB jedoch im Wesentlichen ein Schlüssel/Wert-Speicher ist, kommt es mit erheblichen Leistungseinschränkungen. Außerdem ist der direkte Zugriff auf Unterabschnitte einer Datei unter IndexedDB noch schwieriger und langsamer.
  • Außerdem wird die CacheStorage-Schnittstelle umfassend unterstützt und für die Speicherung großer Datenmengen wie Webanwendungsressourcen optimiert. Die Werte sind jedoch unveränderlich.

Die Storage Foundation API versucht, alle Lücken der vorherigen Speicheroptionen zu schließen. Sie ermöglicht die leistungsstarke Speicherung änderbarer großer Dateien, die im Ursprung der Anwendung definiert sind.

Empfohlene Anwendungsfälle für die Storage Foundation API

Beispiele für Websites, die diese API verwenden können:

  • Produktivitäts- oder Kreativitäts-Apps, die mit großen Mengen an Video-, Audio- oder Bilddaten arbeiten Solche Anwendungen können Segmente auf die Festplatte auslagern, anstatt sie im Speicher zu speichern.
  • Anwendungen, die auf einem nichtflüchtigen Dateisystem basieren, auf das über Wasm zugegriffen werden kann, und die mehr Leistung benötigen, als IDBFS garantieren kann.

Was ist die Storage Foundation API?

Die API besteht aus zwei Hauptteilen:

  • Dateisystemaufrufe, die grundlegende Funktionen für die Interaktion mit Dateien und Dateipfaden bieten.
  • Datei-Handles, die Lese- und Schreibzugriff auf eine vorhandene Datei gewähren.

Dateisystemaufrufe

Die Storage Foundation API führt das neue Objekt storageFoundation ein, das auf dem window-Objekt lebt und eine Reihe von Funktionen enthält:

  • storageFoundation.open(name): Öffnet die Datei mit dem angegebenen Namen, falls vorhanden, und erstellt ansonsten eine neue Datei. Gibt ein Versprechen zurück, das mit der geöffneten Datei aufgelöst wird.
  • storageFoundation.delete(name): Entfernt die Datei mit dem angegebenen Namen. Gibt ein Versprechen zurück, das aufgelöst wird, wenn die Datei gelöscht wird.
  • storageFoundation.rename(oldName, newName): Benennt die Datei automatisch vom alten in den neuen Namen um. Gibt ein Versprechen zurück, das beim Umbenennen der Datei aufgelöst wird.
  • storageFoundation.getAll(): gibt ein Versprechen zurück, das mit einem Array aller vorhandenen Dateinamen aufgelöst wird.
  • storageFoundation.requestCapacity(requestedCapacity): Fordert neue Kapazität (in Byte) für die Nutzung durch den aktuellen Ausführungskontext an. Gibt ein Promise zurück, das mit der verbleibenden verfügbaren Kapazität aufgelöst wurde.
  • storageFoundation.releaseCapacity(toBeReleasedCapacity): Gibt die angegebene Anzahl von Byte aus dem aktuellen Ausführungskontext frei und gibt ein Versprechen zurück, das mit der verbleibenden Kapazität aufgelöst wird.
  • storageFoundation.getRemainingCapacity(): Gibt ein Versprechen zurück, das mit der für den aktuellen Ausführungskontext verfügbaren Kapazität aufgelöst wird.

Datei-Aliasse

Die Arbeit mit Dateien erfolgt über die folgenden Funktionen:

  • NativeIOFile.close(): Schließt eine Datei und gibt ein Versprechen zurück, das nach Abschluss des Vorgangs aufgelöst wird.
  • NativeIOFile.flush(): Synchronisiert (d. h. leer) den speicherinternen Status einer Datei mit dem Speichergerät und gibt ein Versprechen zurück, das nach Abschluss des Vorgangs aufgelöst wird.
  • NativeIOFile.getLength(): gibt ein Versprechen zurück, das mit der Länge der Datei in Byte aufgelöst wird.
  • NativeIOFile.setLength(length): Legt die Länge der Datei in Byte fest und gibt ein Versprechen zurück, das nach Abschluss des Vorgangs aufgelöst wird. Wenn die neue Länge kleiner als die aktuelle Länge ist, werden die Byte ab dem Ende der Datei entfernt. Andernfalls wird die Datei um Byte mit dem Wert null erweitert.
  • NativeIOFile.read(buffer, offset): Liest den Inhalt der Datei mit dem angegebenen Offset über einen Puffer, der das Ergebnis der Übertragung des angegebenen Zwischenspeichers ist, der dann getrennt bleibt. Gibt eine NativeIOReadResult mit dem übertragenen Zwischenspeicher und der Anzahl der erfolgreich gelesenen Byte zurück.

    Ein NativeIOReadResult ist ein Objekt, das aus zwei Einträgen besteht:

    • buffer: Ein ArrayBufferView, das das Ergebnis der Übertragung des an read() übergebenen Zwischenspeichers ist. Sie hat denselben Typ und dieselbe Länge wie der Quellpuffer.
    • readBytes: Die Anzahl der Byte, die erfolgreich in buffer gelesen wurden. Diese kann kleiner als die Puffergröße sein, wenn ein Fehler auftritt oder der Lesebereich über das Ende der Datei hinausgeht. Er wird auf null gesetzt, wenn der Lesebereich das Ende der Datei überschreitet.
  • NativeIOFile.write(buffer, offset): Schreibt den Inhalt des angegebenen Zwischenspeichers im angegebenen Offset in die Datei. Der Puffer wird übertragen, bevor Daten geschrieben werden, und bleibt daher getrennt. Gibt eine NativeIOWriteResult mit dem übertragenen Zwischenspeicher und der Anzahl der erfolgreich geschriebenen Byte zurück. Die Datei wird erweitert, wenn der Schreibbereich ihre Länge überschreitet.

    Ein NativeIOWriteResult ist ein Objekt, das aus zwei Einträgen besteht:

    • buffer: Ein ArrayBufferView, das das Ergebnis der Übertragung des an write() übergebenen Zwischenspeichers ist. Sie hat denselben Typ und dieselbe Länge wie der Quellpuffer.
    • writtenBytes: Die Anzahl der Byte, die erfolgreich in buffer geschrieben wurden. Diese kann kleiner als die Puffergröße sein, wenn ein Fehler auftritt.

Vollständige Beispiele

Zur Verdeutlichung der oben vorgestellten Konzepte finden Sie hier zwei vollständige Beispiele, die Sie durch die verschiedenen Phasen des Lebenszyklus von Storage Foundation-Dateien führen.

Öffnen, Schreiben, Lesen, Schließen

// Open a file (creating it if needed).
const file = await storageFoundation.open('test_file');
try {
  // Request 100 bytes of capacity for this context.
  await storageFoundation.requestCapacity(100);

  const writeBuffer = new Uint8Array([64, 65, 66]);
  // Write the buffer at offset 0. After this operation, `result.buffer`
  // contains the transferred buffer and `result.writtenBytes` is 3,
  // the number of bytes written. `writeBuffer` is left detached.
  let result = await file.write(writeBuffer, 0);

  const readBuffer = new Uint8Array(3);
  // Read at offset 1. `result.buffer` contains the transferred buffer,
  // `result.readBytes` is 2, the number of bytes read. `readBuffer` is left
  // detached.
  result = await file.read(readBuffer, 1);
  // `Uint8Array(3) [65, 66, 0]`
  console.log(result.buffer);
} finally {
  file.close();
}

Öffnen, Auflisten, Löschen

// Open three different files (creating them if needed).
await storageFoundation.open('sunrise');
await storageFoundation.open('noon');
await storageFoundation.open('sunset');
// List all existing files.
// `["sunset", "sunrise", "noon"]`
await storageFoundation.getAll();
// Delete one of the three files.
await storageFoundation.delete('noon');
// List all remaining existing files.
// `["sunrise", "noon"]`
await storageFoundation.getAll();

Demo

Sie können die Storage Foundation API-Demo unten ausprobieren. Sie können Dateien erstellen, umbenennen, in sie schreiben und daraus lesen. Außerdem können Sie die verfügbare Kapazität sehen, die Sie aktualisiert haben, während Sie Änderungen vornehmen. Den Quellcode der Demo findest du auf Glitch.

Sicherheit und Berechtigungen

Das Chromium-Team hat die Storage Foundation API gemäß den Grundprinzipien entwickelt und implementiert, die unter Zugriff auf leistungsstarke Webplattformfunktionen steuern, einschließlich Nutzersteuerung, Transparenz und Ergonomie, definiert wurden.

Ähnlich wie bei anderen modernen Storage-APIs im Web ist der Zugriff auf die Storage Foundation API ursprungsgebunden, d. h., ein Ursprung kann nur auf selbst erstellte Daten zugreifen. Sie ist außerdem auf sichere Kontexte beschränkt.

Nutzersteuerung

Das Speicherkontingent wird verwendet, um den Zugriff auf den Speicherplatz zu verteilen und Missbrauch zu verhindern. Der Arbeitsspeicher, den Sie belegen möchten, muss zuerst angefordert werden. Wie bei anderen Storage-APIs können Nutzer den von der Storage Foundation API belegten Speicherplatz über ihren Browser freigeben.

Nützliche Links

Danksagungen

Die Storage Foundation API wurde von Emanuel Krivoy und Richard Stotz spezifiziert und implementiert. Dieser Artikel wurde von Pete LePage und Joe Medley geprüft.

Hero-Image über Markus Spiske auf Unsplash