Eine schnelle, aber vollständige Anleitung zu IndexedDB und zum Speichern von Daten in Browsern

Möchten Sie JavaScript lernen? Holen Sie sich mein JavaScript-eBook bei jshandbook.com

Einführung in IndexedDB

IndexedDB ist eine der Speicherfunktionen, die im Laufe der Jahre in Browsern eingeführt wurden.

Es ist ein Schlüssel- / Wertspeicher (eine noSQL-Datenbank), der als endgültige Lösung zum Speichern von Daten in Browsern angesehen wird .

Es handelt sich um eine asynchrone API. Dies bedeutet, dass das Ausführen kostspieliger Vorgänge den UI-Thread nicht blockiert und den Benutzern eine schlampige Erfahrung bietet. Es kann eine unbestimmte Datenmenge speichern, obwohl der Benutzer nach einem bestimmten Schwellenwert aufgefordert wird, der Site höhere Grenzwerte zu geben.

Es wird von allen modernen Browsern unterstützt.

Es unterstützt Transaktionen, Versionierung und bietet eine gute Leistung.

Im Browser können wir auch verwenden:

  • Cookies : können eine sehr kleine Anzahl von Zeichenfolgen enthalten
  • Web Storage (oder DOM Storage), ein Begriff, der üblicherweise localStorage und sessionStorage, zwei Schlüssel- / Wertspeicher, identifiziert. sessionStorage speichert keine Daten, die beim Beenden der Sitzung gelöscht werden, während localStorage die Daten über Sitzungen hinweg aufbewahrt

Lokaler Speicher / Sitzungsspeicher hat den Nachteil, dass er auf eine kleine (und inkonsistente) Größe begrenzt ist. Die Browserimplementierung bietet 2 bis 10 MB Speicherplatz pro Standort.

In der Vergangenheit hatten wir auch Web SQL , einen Wrapper für SQLite, aber jetzt ist dies in einigen modernen Browsern veraltet und wird nicht mehr unterstützt. Es war nie ein anerkannter Standard und sollte daher nicht verwendet werden, obwohl 83% der Benutzer diese Technologie auf ihrem Computer haben Geräte nach Kann ich verwenden.

Während Sie technisch mehrere Datenbanken pro Site erstellen können, erstellen Sie im Allgemeinen eine einzelne Datenbank , und innerhalb dieser Datenbank können Sie mehrere Objektspeicher erstellen .

Eine Datenbank ist für eine Domain privat , sodass keine andere Site auf eine andere Website zugreifen kann. IndexedDB speichert.

Jedes Geschäft enthält normalerweise eine Reihe von Dingen , die sein können

  • Saiten
  • Zahlen
  • Objekte
  • Arrays
  • Termine

Beispielsweise könnten Sie ein Geschäft haben, das Beiträge enthält, ein anderes, das Kommentare enthält.

Ein Geschäft enthält eine Reihe von Artikeln mit einem eindeutigen Schlüssel, der die Art und Weise darstellt, wie ein Objekt identifiziert werden kann.

Sie können diese Speicher mithilfe von Transaktionen ändern, indem Sie Vorgänge zum Hinzufügen, Bearbeiten und Löschen ausführen und die darin enthaltenen Elemente durchlaufen.

Seit dem Aufkommen des Promises in ES6, und die anschließende Bewegung von APIs Versprechen verwenden, scheint die IndexedDB API ein wenig der alten Schule .

Es ist zwar nichts Falsches daran, aber in allen Beispielen, die ich erläutern werde, werde ich die IndexedDB Promised Library von Jake Archibald verwenden, eine winzige Ebene über der IndexedDB-API, um die Verwendung zu vereinfachen.

Diese Bibliothek wird auch für alle Beispiele auf der Google Developers-Website zu IndexedDB verwendet

Erstellen Sie eine IndexedDB-Datenbank

Am einfachsten ist es, unpkg zu verwenden , indem Sie dies dem Seitenkopf hinzufügen:

 import { openDB, deleteDB } from '//unpkg.com/idb?module'  

Stellen Sie vor der Verwendung der IndexedDB-API immer sicher, dass Sie den Browser auf Unterstützung prüfen, obwohl er weit verbreitet ist. Sie wissen nie, welchen Browser der Benutzer verwendet:

(() => { 'use strict' if (!('indexedDB' in window)) { console.warn('IndexedDB not supported') return } //...IndexedDB code })() 

So erstellen Sie eine Datenbank

Verwenden von openDB():

(async () => { //... const dbName = 'mydbname' const storeName = 'store1' const version = 1 //versions start at 1 const db = await openDB(dbName, version, { upgrade(db, oldVersion, newVersion, transaction) { const store = db.createObjectStore(storeName) } }) })() 

Die ersten beiden Parameter sind der Datenbankname und die Verson. Der dritte Parameter, der optional ist, ist ein Objekt, das eine Funktion enthält, die nur aufgerufen wird, wenn die Versionsnummer höher als die aktuell installierte Datenbankversion ist . Im Funktionskörper können Sie die Struktur (Speicher und Indizes) der Datenbank aktualisieren.

Hinzufügen von Daten zu einem Geschäft

Hinzufügen von Daten beim Erstellen des Speichers, Initialisieren

Sie verwenden die putMethode des Objektspeichers, aber zuerst benötigen wir einen Verweis darauf, den wir db.createObjectStore()beim Erstellen abrufen können.

Bei Verwendung putist der Wert das erste Argument, der Schlüssel das zweite. Dies liegt daran, dass Sie, wenn Sie keyPathbeim Erstellen des Objektspeichers angeben , nicht bei jeder put () -Anforderung den Schlüsselnamen eingeben müssen, sondern nur den Wert schreiben können.

Dies wird ausgefüllt store0, sobald wir es erstellen:

(async () => { //... const dbName = 'mydbname' const storeName = 'store0' const version = 1 const db = await openDB(dbName, version,{ upgrade(db, oldVersion, newVersion, transaction) { const store = db.createObjectStore(storeName) store.put('Hello world!', 'Hello') } }) })() 

Hinzufügen von Daten, wenn der Speicher bereits erstellt wurde, mithilfe von Transaktionen

Um Elemente später auf der Straße hinzufügen können , müssen Sie eine Lese- / Schreib erstellen Transaktion , die sicherstellt , die Integrität der Datenbank (wenn ein Vorgang fehlschlägt, alle Operationen in der Transaktion zurückgerollt und der Zustand geht zurück auf einen bekannten Zustand).

Verwenden Sie dazu einen Verweis auf das dbPromiseObjekt, das wir beim Aufruf erhalten haben openDB, und führen Sie Folgendes aus:

(async () => { //... const dbName = 'mydbname' const storeName = 'store0' const version = 1 const db = await openDB(/* ... */) const tx = db.transaction(storeName, 'readwrite') const store = await tx.objectStore(storeName) const val = 'hey!' const key = 'Hello again' const value = await store.put(val, key) await tx.done })() 

Daten aus einem Geschäft abrufen

Einen Artikel aus einem Geschäft beziehen: get()

const key = 'Hello again' const item = await db.transaction(storeName).objectStore(storeName).get(key) 

Alle Artikel aus einem Geschäft beziehen: getAll()

Holen Sie sich alle Schlüssel gespeichert

const items = await db.transaction(storeName).objectStore(storeName).getAllKeys() 

Holen Sie sich alle Werte gespeichert

const items = await db.transaction(storeName).objectStore(storeName).getAll() 

Daten aus IndexedDB löschen

Löschen der Datenbank, eines Objektspeichers und von Daten

Löschen Sie eine gesamte IndexedDB-Datenbank

const dbName = 'mydbname' await deleteDB(dbName) 

Daten in einem Objektspeicher löschen

Wir verwenden eine Transaktion:

(async () => { //... const dbName = 'mydbname' const storeName = 'store1' const version = 1 const db = await openDB(dbName, version, { upgrade(db, oldVersion, newVersion, transaction) { const store = db.createObjectStore(storeName) } }) const tx = await db.transaction(storeName, 'readwrite') const store = await tx.objectStore(storeName) const key = 'Hello again' await store.delete(key) await tx.done })() 

Migrieren Sie von einer früheren Version einer Datenbank

The third (optional) parameter of the openDB() function is an object that can contain an upgrade function called only if the version number is higher than the current installed database version. In that function body you can upgrade the structure (stores and indexes) of the db:

const name = 'mydbname' const version = 1 openDB(name, version, { upgrade(db, oldVersion, newVersion, transaction) { console.log(oldVersion) } }) 

In this callback, you can check from which version the user is updating, and perform some operations accordingly.

You can perform a migration from a previous database version using this syntax

(async () => { //... const dbName = 'mydbname' const storeName = 'store0' const version = 1 const db = await openDB(dbName, version, { upgrade(db, oldVersion, newVersion, transaction) { switch (oldVersion) { case 0: // no db created before // a store introduced in version 1 db.createObjectStore('store1') case 1: // a new store in version 2 db.createObjectStore('store2', { keyPath: 'name' }) } db.createObjectStore(storeName) } }) })() 

Unique keys

createObjectStore() as you can see in case 1 accepts a second parameter that indicates the index key of the database. This is very useful when you store objects: put() calls don't need a second parameter, but can just take the value (an object) and the key will be mapped to the object property that has that name.

The index gives you a way to retrieve a value later by that specific key, and it must be unique (every item must have a different key)

A key can be set to auto increment, so you don't need to keep track of it on the client code:

db.createObjectStore('notes', { autoIncrement: true }) 

Use auto increment if your values do not contain a unique key already (for example, if you collect email addresses without an associated name).

Check if a store exists

You can check if an object store already exists by calling the objectStoreNames() method:

const storeName = 'store1' if (!db.objectStoreNames.contains(storeName)) { db.createObjectStore(storeName) } 

Deleting from IndexedDB

Deleting the database, an object store and data

Delete a database

await deleteDB('mydb') 

Delete an object store

An object store can only be deleted in the callback when opening a db, and that callback is only called if you specify a version higher than the one currently installed:

const db = await openDB('dogsdb', 2, { upgrade(db, oldVersion, newVersion, transaction) { switch (oldVersion) { case 0: // no db created before // a store introduced in version 1 db.createObjectStore('store1') case 1: // delete the old store in version 2, create a new one db.deleteObjectStore('store1') db.createObjectStore('store2') } } }) 

To delete data in an object store use a transaction

const key = 232 //a random key const db = await openDB(/*...*/) const tx = await db.transaction('store', 'readwrite') const store = await tx.objectStore('store') await store.delete(key) await tx.complete 

There's more!

Dies sind nur die Grundlagen. Ich habe nicht über Cursor und fortgeschrittenere Sachen gesprochen. IndexedDB bietet noch mehr, aber ich hoffe, dies verschafft Ihnen einen Vorsprung.

Möchten Sie JavaScript lernen? Holen Sie sich mein JavaScript-Buch bei jshandbook.com