Vrei să înveți JavaScript? Obțineți cartea mea electronică JavaScript la jshandbook.com

Introducere în IndexedDB

IndexedDB este una dintre capacitățile de stocare introduse în browsere de-a lungul anilor.
Este un depozit de chei / valori (o bază de date noSQL) considerat a fi soluția definitivă pentru stocarea datelor în browsere.

Este un API asincron, ceea ce înseamnă că efectuarea de operațiuni costisitoare nu va bloca firul UI oferind utilizatorilor o experiență neglijentă. Poate stoca o cantitate nedeterminată de date, deși odată depășit un anumit prag, utilizatorul este solicitat să dea site-ului limite mai mari.

este acceptat pe toate browserele moderne.

Acceptă tranzacții, versiuni și oferă performanțe bune.

În browser putem folosi și:

  • Cookie-uri: poate găzdui o cantitate foarte mică de corzi
  • Stocare web (sau DOM Storage), un termen care identifică în mod obișnuit localStorage și sessionStorage, două stocuri de chei / valori. sessionStorage, nu reține datele, care sunt șterse la sfârșitul sesiunii, în timp ce localStorage păstrează datele între sesiuni

Spațiul de stocare local / sesiune are dezavantajul că este limitat la o dimensiune mică (și inconsistentă), implementarea browserelor oferind de la 2 MB la 10 MB spațiu pe site.

În trecut am avut și noi Web SQL, un wrapper în jurul SQLite, dar acum este depreciat și neacceptat pe unele browsere moderne, nu a fost niciodată un standard recunoscut și, prin urmare, nu ar trebui utilizat, deși 83% dintre utilizatori au această tehnologie pe dispozitivele lor conform Pot folosi.

Deși puteți crea tehnic mai multe baze de date pe site, în general creați o singură bază de date, și în interiorul acelei baze de date puteți crea depozite de obiecte multiple.

O bază de date este privat pentru un domeniu, deci orice alt site nu poate accesa un alt site magazin IndexedDB.

Fiecare magazin conține de obicei un set de lucruri, care poate fi

  • siruri de caractere
  • numere
  • obiecte
  • matrice
  • datele

De exemplu, este posibil să aveți un magazin care conține postări, altul care conține comentarii.

Un magazin conține un număr de articole care au o cheie unică, care reprezintă modul prin care un obiect poate fi identificat.

Puteți modifica acele magazine utilizând tranzacții, efectuând operații de adăugare, editare și ștergere și iterare asupra articolelor pe care le conțin.

De la apariția Promisiuni în ES6 și mutarea ulterioară a API-urilor către utilizarea promisiunilor, API-ul IndexedDB pare puțin vechea scoala.

Deși nu este nimic în neregulă în acesta, în toate exemplele pe care le voi explica, le voi folosi Biblioteca promisă IndexedDB de Jake Archibald, care este un strat mic deasupra API-ului IndexedDB pentru a fi mai ușor de utilizat.

Această bibliotecă este, de asemenea, utilizată pe toate exemplele de pe site-ul web Google Developers cu privire la IndexedDB

Creați o bază de date IndexedDB

Cel mai simplu mod este de a folosi despachetează, adăugând acest lucru la antetul paginii:

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

Înainte de a utiliza API-ul IndexedDB, asigurați-vă întotdeauna că verificați dacă există suport în browser, chiar dacă este disponibil pe scară largă, nu știți niciodată ce browser utilizează utilizatorul:

(() => {
  'use strict'

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

  //...IndexedDB code
})()

Cum să creați o bază de date

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

Primii 2 parametri sunt numele bazei de date și versonul. Al treilea param, care este opțional, este un obiect care conține o funcție apelat numai dacă numărul versiunii este mai mare decât versiunea curentă a bazei de date instalate. În corpul funcției puteți actualiza structura (magazine și indici) a db-ului.

Adăugarea de date într-un magazin

Adăugarea de date la crearea magazinului, inițializarea acestuia

Folosiți put metoda depozitului de obiecte, dar mai întâi avem nevoie de o referință la aceasta, din care putem obține db.createObjectStore() când îl creăm.

Atunci când se utilizează put, valoarea este primul argument, cheia este al doilea. Acest lucru se datorează faptului că, dacă specificați keyPath atunci când creați magazinul de obiecte, nu este necesar să introduceți numele cheii la fiecare cerere put (), puteți scrie doar valoarea.

Aceasta populează store0 imediat ce îl creăm:

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

Adăugarea de date atunci când magazinul este deja creat, utilizând tranzacții

Pentru a adăuga articole mai târziu, trebuie să creați o citire / scriere tranzacţie, care asigură integritatea bazei de date (în cazul în care o operațiune eșuează, toate operațiunile din tranzacție sunt anulate și starea revine la o stare cunoscută).

Pentru aceasta, utilizați o referință la dbPromise obiect pe care l-am obținut atunci când sunăm openDB, și fugi:

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

Obținerea datelor dintr-un magazin

Obținerea unui articol dintr-un magazin: get()

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

Obținerea tuturor articolelor dintr-un magazin: getAll()

Primiți toate cheile stocate

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

Obțineți toate valorile stocate

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

Ștergerea datelor din IndexedDB

Ștergerea bazei de date, a unui depozit de obiecte și a datelor

Ștergeți o întreagă bază de date IndexedDB

const dbName="mydbname"
await deleteDB(dbName)

Pentru a șterge datele dintr-un depozit de obiecte

Folosim o tranzacție:

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

Migrați din versiunea anterioară a unei baze de date

Al treilea parametru (opțional) al fișierului openDB() funcția este un obiect care poate conține un upgrade funcţie apelat numai dacă numărul versiunii este mai mare decât versiunea curentă a bazei de date instalate. În corpul funcției respective puteți actualiza structura (magazine și indici) a db-ului:

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

În acest apel invers, puteți verifica din ce versiune actualizează utilizatorul și efectua unele operațiuni în consecință.

Puteți efectua o migrare dintr-o versiune anterioară a bazei de date folosind această sintaxă

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

Taste unice

createObjectStore() după cum puteți vedea în case 1 acceptă un al doilea parametru care indică cheia index a bazei de date. Acest lucru este foarte util atunci când stocați obiecte: put() apelurile nu au nevoie de un al doilea parametru, ci pot lua doar valoarea (un obiect), iar cheia va fi mapată la proprietatea obiectului care are acel nume.

Indexul vă oferă o modalitate de a extrage o valoare ulterior prin acea cheie specifică și trebuie să fie unică (fiecare element trebuie să aibă o cheie diferită)

O cheie poate fi setată la creșterea automată, deci nu este nevoie să o urmăriți în codul clientului:

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

Utilizați incrementarea automată dacă valorile dvs. nu conțin deja o cheie unică (de exemplu, dacă colectați adrese de e-mail fără un nume asociat).

Verificați dacă există un magazin

Puteți verifica dacă există deja un depozit de obiecte apelând objectStoreNames() metodă:

const storeName="store1"

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

Ștergerea din IndexedDB

Ștergerea bazei de date, a unui depozit de obiecte și a datelor

Ștergeți o bază de date

await deleteDB('mydb')

Ștergeți un depozit de obiecte

Un depozit de obiecte poate fi șters numai în callback atunci când deschideți un db, iar acel callback este apelat numai dacă specificați o versiune mai mare decât cea instalată în prezent:

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

Pentru a șterge datele dintr-un depozit de obiecte, utilizați o tranzacție

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

Mai este!

Acestea sunt doar elementele de bază. Nu am vorbit despre cursoare și lucruri mai avansate. Există mai multe în IndexedDB, dar sper că acest lucru vă oferă un avans.

Vrei să înveți JavaScript? Obțineți cartea mea JavaScript la jshandbook.com