Plongez dans IndexedDB

IndexedDB est l'une des capacités de stockage introduites dans les navigateurs au fil des ans. Voici une introduction à IndexedDB, la base de données du Web prise en charge par tous les navigateurs modernes

Introduction à IndexedDB

IndexedDB est l'une des capacités de stockage introduites dans les navigateurs au fil des ans. C'est un magasin clé / valeur (une base de données noSQL) considéré commela solution définitive pour stocker des données dans les navigateurs.

C'est une API asynchrone, ce qui signifie que l'exécution d'opérations coûteuses ne bloquera pas le thread d'interface utilisateur, offrant une expérience bâclée aux utilisateurs. Il peut stocker une quantité indéfinie de données, bien qu'une fois au-dessus d'un certain seuil, l'utilisateur soit invité à donner au site des limites plus élevées.

C'estpris en charge sur tous les navigateurs modernes.

Il prend en charge les transactions, la gestion des versions et donne de bonnes performances.

Dans le navigateur, nous pouvons également utiliser:

  • Biscuits: peut héberger une très petite quantité de chaînes
  • Espace archivage sur le Web(ou DOM Storage), un terme qui identifie généralement localStorage et sessionStorage, deux magasins clé / valeur. sessionStorage, ne conserve pas les données, qui sont effacées à la fin de la session, tandis que localStorage conserve les données entre les sessions

Le stockage local / de session a l'inconvénient d'être limité à une taille petite (et incohérente), la mise en œuvre des navigateurs offrant de 2 Mo à 10 Mo d'espace par site.

Dans le passé, nous avions aussiSQL Web, un wrapper autour de SQLite, mais maintenant c'estobsolèteet non pris en charge sur certains navigateurs modernes, cela n'a jamais été une norme reconnue et ne devrait donc pas être utilisé, bien que 83% des utilisateurs aient cette technologie sur leurs appareilsselon Puis-je utiliser.

Bien que vous puissiez techniquement créer plusieurs bases de données par site, vouscréer une seule base de données, et à l'intérieur de cette base de données, vous pouvez créerplusieurs magasins d'objets.

Une base de données estprivé à un domaine, de sorte qu'aucun autre site ne peut accéder à un autre site Web des magasins IndexedDB.

Chaque magasin contient généralement un ensemble dedes choses, qui peut être

  • cordes
  • Nombres
  • objets
  • tableaux
  • Rendez-vous

Par exemple, vous pourriez avoir un magasin qui contient des articles, un autre qui contient des commentaires.

Un magasin contient un certain nombre d'éléments qui ont une clé unique, qui représente la façon dont un objet peut être identifié.

Vous pouvez modifier ces magasins à l'aide de transactions, en effectuant des opérations d'ajout, de modification et de suppression et en effectuant une itération sur les éléments qu'ils contiennent.

Depuis l'avènement dePromessesdans ES6, et le passage ultérieur des API à l'utilisation des promesses, l'API IndexedDB semble un peuvieille école.

Bien qu'il n'y ait rien de mal à cela, dans tous les exemples que je vais expliquer, je vais utiliser leBibliothèque promise IndexedDBpar Jake Archibald, qui est une petite couche au-dessus de l'API IndexedDB pour la rendre plus facile à utiliser.

Cette bibliothèque est également utilisée sur tous les exemples sur le site Web de Google Developers concernant IndexedDB

Créer une base de données IndexedDB

Le moyen le plus simple est d'utiliserunpkg, en ajoutant ceci à l'en-tête de la page:

<script type="module">
import { openDB, deleteDB } from 'https://unpkg.com/idb?module'
</script>

Avant d'utiliser l'API IndexedDB, assurez-vous toujours de vérifier la prise en charge dans le navigateur, même si elle est largement disponible, vous ne savez jamais quel navigateur l'utilisateur utilise:

(() => {
  'use strict'

if (!(‘indexedDB’ in window)) { console.warn(‘IndexedDB not supported’) return }

//…IndexedDB code })()

Commentcréer une base de données

UtilisantopenDB():

(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)
    }
  })
})()

Les 2 premiers paramètres sont le nom de la base de données et la version. Le troisième paramètre, qui est facultatif, est un objet qui contient une fonctionappelé uniquement si le numéro de version est supérieur à la version actuelle de la base de données installée. Dans le corps de la fonction, vous pouvez mettre à jour la structure (magasins et index) de la base de données.

Ajouter des données dans un magasin

Ajouter des données lors de la création du magasin, l'initialiser

Vous utilisez leputméthode du magasin d'objets, mais nous avons d'abord besoin d'une référence à celle-ci, à partir de laquelle nous pouvons obtenirdb.createObjectStore()quand nous le créons.

Lors de l'utilisationput, la valeur est le premier argument, la clé est le second. C'est parce que si vous spécifiezkeyPathlors de la création du magasin d'objets, vous n'avez pas besoin de saisir le nom de la clé à chaque requête put (), vous pouvez simplement écrire la valeur.

Cela remplitstore0dès que nous le créons:

(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’) } }) })()

Ajout de données lorsque le magasin est déjà créé, à l'aide de transactions

Pour ajouter des éléments ultérieurement, vous devez créer un fichier en lecture / écrituretransaction, qui garantit l'intégrité de la base de données (si une opération échoue, toutes les opérations de la transaction sont annulées et l'état revient à un état connu).

Pour cela, utilisez une référence audbPromiseobjet que nous avons obtenu lors de l'appelopenDB, et courir:

(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 })()

Obtenir des données d'un magasin

Obtenir un article dans un magasin:get()

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

Obtenir tous les articles d'un magasin:getAll()

Obtenez toutes les clés stockées

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

Obtenez toutes les valeurs stockées

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

Suppression de données d'IndexedDB

Suppression de la base de données, d'un magasin d'objets et des données

Supprimer une base de données IndexedDB entière

const dbName = 'mydbname'
await deleteDB(dbName)

Pour supprimer des données dans un magasin d'objets

Nous utilisons une transaction:

(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 })()

Migrer depuis la version précédente d'une base de données

Le troisième paramètre (facultatif) de laopenDB()function est un objet qui peut contenir unupgradefonctionappelé uniquement si le numéro de version est supérieur à la version actuelle de la base de données installée. Dans ce corps de fonction, vous pouvez mettre à niveau la structure (magasins et index) de la base de données:

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

Dans ce rappel, vous pouvez vérifier à partir de quelle version l'utilisateur met à jour et effectuer certaines opérations en conséquence.

Vous pouvez effectuer une migration à partir d'une version de base de données précédente en utilisant cette syntaxe

(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) } }) })()

Clés uniques

createObjectStore()comme vous pouvez le voir danscase 1accepte un deuxième paramètre qui indique la clé d'index de la base de données. Ceci est très utile lorsque vous stockez des objets:put()les appels n'ont pas besoin d'un deuxième paramètre, mais peuvent simplement prendre la valeur (un objet) et la clé sera mappée à la propriété d'objet qui porte ce nom.

L'index vous donne un moyen de récupérer une valeur plus tard par cette clé spécifique, et il doit être unique (chaque élément doit avoir une clé différente)

Une clé peut être définie sur incrémentation automatique, vous n'avez donc pas besoin de la suivre sur le code client:

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

Utilisez l'incrémentation automatique si vos valeurs ne contiennent pas déjà de clé unique (par exemple, si vous collectez des adresses e-mail sans nom associé).

Vérifier si un magasin existe

Vous pouvez vérifier si un magasin d'objets existe déjà en appelant leobjectStoreNames()méthode:

const storeName = 'store1'

if (!db.objectStoreNames.contains(storeName)) { db.createObjectStore(storeName) }

Suppression de IndexedDB

Suppression de la base de données, d'un magasin d'objets et des données

Supprimer une base de données

await deleteDB('mydb')

Supprimer un magasin d'objets

Un magasin d'objets ne peut être supprimé dans le rappel que lors de l'ouverture d'une base de données, et ce rappel n'est appelé que si vous spécifiez une version supérieure à celle actuellement installée:

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')
    }
  }
})

Pour supprimer des données dans un magasin d'objets, utilisez une 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

Il y a plus!

Ce ne sont que les bases. Je n'ai pas parlé de curseurs et de trucs plus avancés. Il y a plus à IndexedDB mais j'espère que cela vous donne une longueur d'avance.

Téléchargez mon gratuitManuel du débutant JavaScript


Plus de didacticiels sur le navigateur: