Sumérjase en IndexedDB

IndexedDB es una de las capacidades de almacenamiento introducidas en los navegadores a lo largo de los años. Aquí hay una introducción a IndexedDB, la base de datos de la Web compatible con todos los navegadores modernos.

Introducción a IndexedDB

IndexedDB es una de las capacidades de almacenamiento introducidas en los navegadores a lo largo de los años. Es un almacén de clave / valor (una base de datos noSQL) que se considerala solución definitiva para almacenar datos en navegadores.

Es una API asincrónica, lo que significa que la realización de operaciones costosas no bloqueará el hilo de la interfaz de usuario, proporcionando una experiencia descuidada a los usuarios. Puede almacenar una cantidad indefinida de datos, aunque una vez que se sobrepasa un cierto umbral, se le pide al usuario que le dé al sitio límites más altos.

Escompatible con todos los navegadores modernos.

Admite transacciones, control de versiones y ofrece un buen rendimiento.

Dentro del navegador también podemos utilizar:

  • Galletas: puede albergar una cantidad muy pequeña de cadenas
  • Almacenamiento web(o almacenamiento DOM), un término que comúnmente identifica localStorage y sessionStorage, dos almacenes clave / valor. sessionStorage, no retiene datos, que se borran cuando finaliza la sesión, mientras que localStorage mantiene los datos entre sesiones

El almacenamiento local / de sesión tiene la desventaja de estar limitado a un tamaño pequeño (e inconsistente), con la implementación de los navegadores que ofrecen de 2 MB a 10 MB de espacio por sitio.

En el pasado también tuvimosWeb SQL, una envoltura alrededor de SQLite, pero ahora esto esobsoletoy no es compatible con algunos navegadores modernos, nunca ha sido un estándar reconocido y, por lo tanto, no debe usarse, aunque el 83% de los usuarios tienen esta tecnología en sus dispositivos.de acuerdo con puedo usar.

Aunque técnicamente puede crear varias bases de datos por sitio, generalmentecrear una sola base de datos, y dentro de esa base de datos puedes crearmúltiples almacenes de objetos.

Una base de datos esprivado a un dominio, por lo que cualquier otro sitio no puede acceder a otro sitio web de las tiendas IndexedDB.

Cada tienda suele contener un conjunto decosas, que puede ser

  • instrumentos de cuerda
  • números
  • objetos
  • matrices
  • fechas

Por ejemplo, puede tener una tienda que contenga publicaciones, otra que contenga comentarios.

Una tienda contiene una serie de artículos que tienen una clave única, que representa la forma en que se puede identificar un objeto.

Puede modificar esas tiendas mediante transacciones, realizando operaciones de agregar, editar y eliminar, e iterar sobre los artículos que contienen.

Desde el advenimiento dePromesasen ES6, y el posterior movimiento de las API para usar promesas, la API IndexedDB parece un pocovieja escuela.

Si bien no hay nada de malo en ello, en todos los ejemplos que explicaré usaré elBiblioteca prometida de IndexedDBpor Jake Archibald, que es una pequeña capa encima de la API IndexedDB para que sea más fácil de usar.

Esta biblioteca también se utiliza en todos los ejemplos en el sitio web de Google Developers con respecto a IndexedDB

Crear una base de datos IndexedDB

La forma más sencilla es utilizarunpkg, agregando esto al encabezado de la página:

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

Antes de usar la API IndexedDB, asegúrese siempre de verificar la compatibilidad en el navegador, aunque está ampliamente disponible, nunca se sabe qué navegador está usando el usuario:

(() => {
  'use strict'

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

//…IndexedDB code })()

Cómocrear una base de datos

UsandoopenDB():

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

Los primeros 2 parámetros son el nombre de la base de datos y la versión. El tercer parámetro, que es opcional, es un objeto que contiene una funciónse llama solo si el número de versión es mayor que la versión actual de la base de datos instalada. En el cuerpo de la función puede actualizar la estructura (almacenes e índices) del archivo db.

Agregar datos a una tienda

Agregar datos cuando se crea la tienda, inicializarla

Usas elputmétodo del almacén de objetos, pero primero necesitamos una referencia a él, que podemos obtener dedb.createObjectStore()cuando lo creamos.

Cuando usasput, el valor es el primer argumento, la clave es el segundo. Esto se debe a que si especificakeyPathal crear el almacén de objetos, no es necesario que ingrese el nombre de la clave en cada solicitud put (), solo puede escribir el valor.

Esto pueblastore0tan pronto como lo creamos:

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

Agregar datos cuando la tienda ya está creada, usando transacciones

Para agregar elementos más adelante en el futuro, debe crear una lectura / escrituratransacción, que asegura la integridad de la base de datos (si una operación falla, todas las operaciones de la transacción se revierten y el estado vuelve a un estado conocido).

Para eso, use una referencia aldbPromiseobjeto que obtuvimos al llamaropenDB, y correr:

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

Obtener datos de una tienda

Obtener un artículo de una tienda:get()

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

Obtener todos los artículos de una tienda:getAll()

Obtener todas las claves almacenadas

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

Obtenga todos los valores almacenados

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

Eliminando datos de IndexedDB

Eliminar la base de datos, un almacén de objetos y datos

Eliminar una base de datos IndexedDB completa

const dbName = 'mydbname'
await deleteDB(dbName)

Para eliminar datos en un almacén de objetos

Usamos una transacción:

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

Migrar desde la versión anterior de una base de datos

El tercer parámetro (opcional) delopenDB()La función es un objeto que puede contener unupgradefunciónse llama solo si el número de versión es mayor que la versión actual de la base de datos instalada. En ese cuerpo de función puede actualizar la estructura (tiendas e índices) de la base de datos:

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

En esta devolución de llamada, puede verificar desde qué versión está actualizando el usuario y realizar algunas operaciones en consecuencia.

Puede realizar una migración desde una versión anterior de la base de datos utilizando esta sintaxis

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

Llaves únicas

createObjectStore()como puedes ver encase 1acepta un segundo parámetro que indica la clave de índice de la base de datos. Esto es muy útil cuando almacena objetos:put()las llamadas no necesitan un segundo parámetro, pero pueden simplemente tomar el valor (un objeto) y la clave se asignará a la propiedad del objeto que tiene ese nombre.

El índice le brinda una forma de recuperar un valor más tarde mediante esa clave específica, y debe ser único (cada elemento debe tener una clave diferente)

Se puede configurar una clave para que aumente automáticamente, por lo que no es necesario realizar un seguimiento de ella en el código del cliente:

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

Utilice el incremento automático si sus valores aún no contienen una clave única (por ejemplo, si recopila direcciones de correo electrónico sin un nombre asociado).

Comprueba si existe una tienda

Puede comprobar si ya existe un almacén de objetos llamando alobjectStoreNames()método:

const storeName = 'store1'

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

Eliminando de IndexedDB

Eliminar la base de datos, un almacén de objetos y datos

Eliminar una base de datos

await deleteDB('mydb')

Eliminar un almacén de objetos

Un almacén de objetos solo se puede eliminar en la devolución de llamada al abrir una base de datos, y esa devolución de llamada solo se llama si especifica una versión superior a la que está instalada actualmente:

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

Para eliminar datos en una tienda de objetos, use una transacción

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

¡Hay más!

Estos son solo los conceptos básicos. No hablé de cursores y cosas más avanzadas. Hay más en IndexedDB, pero espero que esto le dé una ventaja.


Más tutoriales de navegador: