Hochleistungsspeicher für Ihre Anwendung: die Storage Foundation API

Die Webplattform bietet Entwicklern zunehmend die Tools, die sie zum Erstellen optimierter Hochleistungsanwendungen für das Web benötigen. Vor allem hat WebAssembly (Wasm) die Tür zu schnellen und leistungsstarken Webanwendungen geöffnet. Mit Technologien wie Emscripten können Entwickler jetzt bewährten und getesteten Code im Web wiederverwenden. Um dieses Potenzial voll auszuschöpfen, müssen Entwickler in Bezug auf Speicher die gleiche Leistungsfähigkeit und Flexibilität haben.

Hier kommt die Storage Foundation API ins Spiel. Die Storage Foundation API ist eine neue, schnelle und unvoreingenommene Storage API, die neue und viel gewünschte Anwendungsfälle für das Web ermöglicht, 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 stellen und so die Funktionslücke zwischen webbasiertem und plattformspezifischem Code reduzieren.

Die Storage Foundation API ähnelt einem sehr einfachen Dateisystem und bietet Entwicklern Flexibilität, da sie generische, einfache und leistungsfähige Primitive bereitstellt, auf denen sie übergeordnete Komponenten erstellen können. Anwendungen können das jeweils beste Tool für ihre Anforderungen nutzen und so die richtige Balance zwischen Nutzerfreundlichkeit, Leistung und Zuverlässigkeit finden.

Warum benötigt das Web eine weitere Storage API?

Die Webplattform bietet Entwicklern eine Reihe von Speicheroptionen, die jeweils für bestimmte Anwendungsfälle entwickelt wurden.

  • Einige dieser Optionen überschneiden sich offensichtlich nicht mit diesem Vorschlag, da sie nur die Speicherung sehr kleiner Datenmengen wie Cookies oder der Web Storage API bestehend aus den Mechanismen sessionStorage und localStorage ermöglichen.
  • Andere Optionen wurden aus verschiedenen Gründen wie der File and Directory Entries API oder WebSQL bereits eingestellt.
  • Die File System Access API hat eine ähnliche API-Oberfläche. Sie dient jedoch dazu, eine Schnittstelle zum Dateisystem des Clients zu erstellen und Zugriff auf Daten zu gewähren, die sich außerhalb des Ursprungs des Ursprungs oder des Browsers befinden. Dieser abweichende Fokus geht mit strengeren Sicherheitsaspekten und höheren Leistungskosten einher.
  • Die IndexedDB API kann für einige Anwendungsfälle der Storage Foundation API als Back-End verwendet werden. Emscripten umfasst beispielsweise IDBFS, ein IndexedDB-basiertes nichtflüchtiges Dateisystem. Da IndexedDB jedoch im Wesentlichen ein Schlüssel/Wert-Speicher ist, bringt dies erhebliche Leistungseinschränkungen mit sich. Darüber hinaus ist der direkte Zugriff auf Unterabschnitte einer Datei unter IndexedDB noch schwieriger und langsamer.
  • Schließlich wird die CacheStorage-Schnittstelle weithin unterstützt und für das Speichern umfangreicher Daten wie Webanwendungsressourcen optimiert. Die Werte sind jedoch unveränderlich.

Mit der Storage Foundation API sollen alle Lücken der vorherigen Speicheroptionen geschlossen werden. Sie ermöglicht die leistungsfähige 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 große Mengen an Video-, Audio- oder Bilddaten verarbeiten Solche Anwendungen können Segmente auf das Laufwerk auslagern, anstatt sie im Speicher zu speichern.
  • Anwendungen, die auf einem nichtflüchtigen Dateisystem basieren, auf das über Wasm zugegriffen werden kann, und die eine höhere 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 bieten Lese- und Schreibzugriff auf eine vorhandene Datei.

Dateisystemaufrufe

Mit der Storage Foundation API wird das neue Objekt storageFoundation eingeführt, das auf dem window-Objekt basiert und eine Reihe von Funktionen enthält:

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

Datei-Handles

Die Arbeit mit Dateien erfolgt über die folgenden Funktionen:

  • NativeIOFile.close(): Schließt eine Datei und gibt ein Promise zurück, das aufgelöst wird, wenn der Vorgang abgeschlossen ist.
  • NativeIOFile.flush(): Synchronisiert (d. h. geleert) den speicherinternen Status einer Datei mit dem Speichergerät und gibt ein Promise zurück, das bei Abschluss des Vorgangs aufgelöst wird.
  • NativeIOFile.getLength(): Gibt ein Promise 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 Promise zurück, das nach Abschluss des Vorgangs aufgelöst wird. Wenn die neue Länge kleiner als die aktuelle ist, werden Byte ab dem Ende der Datei entfernt. Andernfalls wird die Datei um nullwertige Byte erweitert.
  • NativeIOFile.read(buffer, offset): Liest den Inhalt der Datei am angegebenen Versatz über einen Zwischenspeicher, der das Ergebnis der Übertragung des angegebenen Zwischenspeichers ist, der dann getrennt bleibt. Gibt ein 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 Zwischenspeichers ist, der an read() übergeben wurde. Er hat den gleichen Typ und die gleiche Länge wie der Quellpuffer.
    • readBytes: Die Anzahl der Byte, die erfolgreich in buffer gelesen wurden. Dieser Wert kann kleiner als die Puffergröße sein, wenn ein Fehler auftritt oder wenn der Lesebereich das Ende der Datei überschreitet. Er wird auf null gesetzt, wenn der Lesebereich außerhalb der Datei liegt.
  • NativeIOFile.write(buffer, offset): Schreibt den Inhalt des angegebenen Zwischenspeichers am angegebenen Versatz in die Datei. Der Zwischenspeicher 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 Zwischenspeichers ist, der an write() übergeben wurde. Er hat denselben Typ und dieselbe Länge wie der Quellpuffer.
    • writtenBytes: Die Anzahl der Byte, die erfolgreich in buffer geschrieben wurden. Dieser Wert 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 im Lebenszyklus von Storage Foundation-Dateien führen.

Öffnen, Schreiben, Lesen, Abschließ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, schreiben und aus ihnen lesen. Außerdem sehen Sie, wie viel Kapazität Sie angefordert hat, wenn Sie Änderungen vornehmen. Den Quellcode der Demo findest du in Glitch.

Sicherheit und Berechtigungen

Das Chromium-Team hat die Storage Foundation API unter Berücksichtigung der unter Zugriff auf leistungsstarke Webplattform-Funktionen steuern definierten Kernprinzipien wie Nutzerkontrolle, Transparenz und Ergonomie entwickelt und implementiert.

Der Zugriff auf die Storage Foundation API folgt demselben Muster wie bei anderen modernen Speicher-APIs im Web. Das bedeutet, dass ein Ursprung nur auf selbst erstellte Daten zugreifen kann. Es ist auch 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 gelesen.

Hero-Image von Markus Spiske auf Unsplash