Nopea, mutta täydellinen opas IndexedDB: hen ja tietojen tallentamiseen selaimissa

Haluatko oppia JavaScriptiä? Hanki ilmainen e-kirjani osoitteesta jshandbook.com

IndexedDB on yksi selainten vuosien varrella käyttöön otetuista tallennusominaisuuksista. Se on avain- / arvovarasto (noSQL-tietokanta), jota pidetään lopullisena ratkaisuna tietojen tallentamiseen selaimissa.

IndexedDB on asynkroninen sovellusliittymä, mikä tarkoittaa, että kalliiden toimintojen suorittaminen ei estä käyttöliittymän ketjua, joka tarjoaa käyttäjille huolimatonta huolta.

Se voi tallentaa määräämättömän määrän tietoja, vaikka tietyn kynnyksen ylittyessä käyttäjää pyydetään antamaan sivustolle korkeammat rajat.

Sitä tuetaan kaikissa nykyaikaisissa selaimissa.

Se tukee tapahtumia ja versiointia ja antaa hyvän suorituskyvyn.

Selaimen sisällä voimme käyttää myös:

  • Evästeet, joihin mahtuu hyvin pieni määrä merkkijonoja
  • DOM-tallennustila (tai Web-tallennustila), termi, joka yleensä tunnistaa localStorage ja sessionStorage, kaksi avain- / arvovarastoa. sessionStorage, ei säilytä tietoja, jotka tyhjennetään istunnon päättyessä, kun taas localStorage pitää tietoja istuntojen välillä

Paikallisella / istuntovarastolla on se haittapuoli, että se on rajoitettu pieneen (ja epäjohdonmukaiseen) kokoon, sillä selainten toteutus tarjoaa 2 Mt - 10 Mt tilaa sivustoa kohden.

Aikaisemmin meillä oli myös Web SQL, kääre SQLiten ympärille. Mutta tämä on nyt vanhentunut, eikä sitä tueta joissain nykyaikaisissa selaimissa. Se ei ole koskaan ollut tunnustettu standardi, joten sitä ei pidä käyttää - vaikka 83 prosentilla käyttäjistä on tämä tekniikka laitteissaan Can I Use -käytännön mukaan.

Vaikka voit teknisesti luoda useita tietokantoja sivustoa kohti, luot yleensä yhden tietokannan. Tietokannan sisällä voit luoda useita objektikauppoja.

Tietokanta on yksityinen verkkotunnukselle, joten mikään muu sivusto ei voi käyttää toisen sivuston IndexedDB-kauppoja.

Jokainen myymälä sisältää yleensä joukon asioita, jotka voivat olla:

  • jouset
  • numerot
  • esineet
  • taulukot
  • päivät

Saatat esimerkiksi olla myymälä, joka sisältää viestejä, ja toinen, joka sisältää kommentteja.

Kauppa sisältää useita tuotteita, joilla on yksilöivä avain, joka edustaa tapaa, jolla kohde voidaan tunnistaa.

Voit muuttaa näitä kauppoja käyttämällä tapahtumia suorittamalla lisäys-, muokkaus- ja poistamistoimintoja sekä toistamalla niiden sisältämiä kohteita.

Koska lupausten tulo ES2015: een ja myöhempi sovellusliittymien siirtyminen lupausten käyttämiseen, IndexedDB-sovellusliittymä näyttää vähän vanhalta koululta.

Vaikka siinä ei ole mitään vikaa, käytän kaikissa selittämissä esimerkeissä Jake Archibaldin IndexedDB Luvattua kirjastoa, joka on pieni kerros IndexedDB API: n päälle, jotta sen käyttö olisi helpompaa.

Tätä kirjastoa käytetään myös kaikissa Google Developers -sivuston esimerkkeissä, jotka koskevat IndexedDB: tä.

Luo indeksoitu DB-tietokanta

Sisällytä idb lib käyttämällä:

lanka lisää idb

Lisää sitten se sivullesi joko käyttämällä Webpackia tai Browserifya tai mitä tahansa muuta rakennusjärjestelmää tai yksinkertaisesti:

Ja olemme valmiita menemään.

Ennen kuin käytät IndexedDB-sovellusliittymää, tarkista aina selaimesta tuki, vaikka se onkin laajalti saatavissa. Et koskaan tiedä mitä selainta käyttäjä käyttää:

(() => {
  'käytä tiukasti'
  if (! ('indeksoituDB' ikkunassa)) {
    console.warn ('IndexedDB: tä ei tueta')
    palata
  }
//...IndexedDB-koodi
}) ()

Kuinka luoda tietokanta

Käyttämällä idb.open ():

const name = 'mydbname'
const version = 1 // versiot alkavat kohdasta 1
idb.open (nimi, versio, upgradeDb => {})

Kaksi ensimmäistä parametria ovat itsestään selviä. Kolmas parametri, joka on valinnainen, on takaisinsoitto, jota kutsutaan vain, jos versionumero on suurempi kuin nykyinen asennettu tietokantaversio. Voit soittaa takaisin -toiminnon rungossa db: n rakenteen (kaupat ja hakemistot).

Käytämme nimessä upgradeDB takaisinsoittoa tunnistaaksemme, että on aika päivittää tietokanta tarvittaessa.

Luo objektikauppa

Kuinka luoda objektivarasto tai lisätä uusi

Objektikauppa luodaan tai päivitetään tässä soittopyynnössä db.createObjectStore ('storeName', asetukset) -sintaksilla:

const dbPromise = idb.open ('mydb', 1, (upgradeDB) => {
  upgradeDB.createObjectStore ( 'myymälä1')
})
. sitten (db => console.log ('menestys'))

Jos olet asentanut aiemman version, soittopyynnön avulla voit suorittaa siirron:

const dbPromise = idb.open ('keyval-store', 3, (upgradeDB) => {
  kytkin (upgradeDB.oldVersion) {
    tapaus 0: // db: tä ei ole luotu aiemmin
      // versiossa 1 esitelty myymälä
      upgradeDB.createObjectStore ( 'myymälä1')
    tapaus 1:
      // uusi myymälä versiossa 2
      upgradeDB.createObjectStore ('store2', {keyPath: 'name'})
  }
})
. sitten (db => console.log ('menestys'))

createObjectStore (), kuten voit nähdä, jos 1 hyväksyy toisen parametrin, joka ilmaisee tietokannan hakemistonäppäimen. Tämä on erittäin hyödyllistä, kun tallennat objekteja: put () -puhelut eivät tarvitse toista parametria, vaan voivat vain ottaa arvon (esine) ja avain yhdistetään objektiominaisuuteen, jolla on kyseinen nimi.

Hakemisto antaa sinulle tavan hakea arvo myöhemmin kyseisellä avaimella, ja sen on oltava ainutlaatuinen (jokaisella kohteella on oltava eri avain).

Avain voidaan asettaa automaattiseen lisäykseen, joten sinun ei tarvitse seurata sitä asiakaskoodissa. Jos et määritä avainta, IndexedDB luo sen meille avoimesti:

upgradeDb.createObjectStore ('huomautukset', {autoIncrement: true})

mutta voit määrittää tietyn objektiarvon kentän myös automaattiseen lisäykseen:

upgradeDb.createObjectStore ('huomautukset', {
  keyPath: 'id',
  autoIncrement: totta
})

Käytä pääsääntöisesti automaattista lisäystä, jos arvoissasi ei ole jo yksilöivää avainta (esimerkiksi käyttäjien sähköpostiosoite).

indeksit

Hakemisto on tapa hakea tietoja esinevarastoista. Se on määritelty idb.open () -soittopyynnön tietokannan luomisen kanssa seuraavasti:

const dbPromise = idb.open ('dogsdb', 1, (upgradeDB) => {
  const koirat = upgradeDB.createObjectStore ('koirat')
  dogs.createIndex ('nimi', 'nimi', {ainutlaatuinen: vääriä})
})

Yksilöivä vaihtoehto määrittää, pitäisikö hakemiston arvon olla yksilöivä, eikä päällekkäisiä arvoja sallita lisätä.

Voit käyttää jo luodtua objektivarastoa päivitysDb.transaction.objectStore () -menetelmällä:

const dbPromise = idb.open ('dogsdb', 1, (upgradeDB) => {
  const koirat = upgradeDB.transaction.objectStore ('koirat')
  dogs.createIndex ('nimi', 'nimi', {ainutlaatuinen: vääriä})
})

Tarkista, onko myymälä olemassa

Voit tarkistaa, onko objektivarasto jo olemassa, soittamalla objectStoreNames () -menetelmään:

if (! upgradeDb.objectStoreNames.contains ('store3')) {
  upgradeDb.createObjectStore ( 'store3')
}

Poistetaan hakemistosta IndexedDB

Poista tietokanta

idb.delete ('mydb'). sitten (() => console.log ('Done'))

Poista esinevarasto

Kohdevarasto voidaan poistaa vain takaisinsoitossa, kun avaat db: n, ja takaisinsoittoon soitetaan vain, jos määrität nykyistä asennettua versiota korkeamman version:

const dbPromise = idb.open ('dogsdb', 2, (upgradeDB) => {
  upgradeDB.deleteObjectStore ( 'old_store')
})

Voit poistaa tietoja objektivarastosta käyttämällä tätä tapahtumaa:

const-avain = 232
dbPromise.then ((db) => {
  const tx = db.transaction ('tallentaa', 'kirjoittaa')
  const store = tx.objectStore ('myymälä')
  store.delete (avain)
  palauta tx.complete
})
. sitten (() => {
  console.log ('Kohde poistettu')
})

Lisää kohde tietokantaan

Voit käyttää objektivaraston put-menetelmää, mutta ensin tarvitsemme siihen viittauksen, jonka saamme päivityksestä upgradeDB.createObjectStore () luotaessa.

Kun käytät put-arvoa, arvo on ensimmäinen argumentti ja avain on toinen. Tämä johtuu siitä, että jos määrität keyPathin objektikauppaa luotaessa, sinun ei tarvitse antaa avaimen nimeä jokaisessa put () -pyynnössä. Voit vain kirjoittaa arvon.

Tämä täyttää store0: n heti, kun olemme luoneet sen:

idb.open ('mydb', 1, (päivitysDB) => {
  keyValStore = upgradeDB.createObjectStore ('store0')
  keyValStore.put ('Hei maailma!', 'Hei')
})

Jos haluat lisätä kohteita myöhemmin tielle, sinun on luotava tapahtuma. Tämä varmistaa tietokannan eheyden (jos toiminto epäonnistuu, kaikki tapahtuman toiminnot kumotaan ja tila palaa takaisin tunnettuun tilaan).

Käytä sitä varten viittaus dbPromise-objektiin, jonka saimme soitettaessa idb.open (), ja suorita:

dbPromise.then ((db) => {
  const val = 'hei!'
  const-avain = 'Hei taas'
  const tx = db.transaction ('store1', 'readwrite')
  tx.objectStore ('store1'). put (val, avain)
  palauta tx.complete
})
. sitten (() => {
  console.log ('Tapahtuma on valmis')
})
.catch (() => {
  console.log ('Tapahtuma epäonnistui')
})

Indeksoitu DB-sovellusliittymä tarjoaa myös add () -menetelmän, mutta koska put () antaa meille mahdollisuuden sekä lisätä että päivittää, sen käyttö on yksinkertaisempaa.

Tuotteiden hankkiminen kaupasta

Tietyn tuotteen hankkiminen myymälästä get (): n avulla

dbPromise.then (db => db.transaction ('objs')
                       .objectStore ( 'objs')
                       .get (123456))
. sitten (obj => console.log (obj))

Kaikkien tuotteiden hakeminen getAll () -sovelluksella

dbPromise.then (db => db.transaction ('store1')
                       .objectStore ( 'myymälä1')
                       .getAll ())
. sitten (esineet => console.log (esineet))

Kaikkien kohteiden iteraaminen kohdistimen avulla openCursorin () kautta

dbPromise.then ((db) => {
  const tx = db.transaction ('tallentaa', 'vain luettavissa')
  const store = tx.objectStore ('myymälä')
  palauta store.openCursor ()
})
. sitten (toimintologit (kohdistin) {
  if (! kohdistin) {return}
  console.log ('kohdistin on:', kohdistin.avain)
  for (const-kenttä kohdistimen arvossa) {
    console.log (cursor.value [kenttä])
  }
  palauta kohdistin. jatka (). sitten (logItems)
})
. sitten (() => {
  console.log ( 'tehty!')
})

Iterointi alajoukkoa esineitä käyttämällä rajoja ja kohdistimia

const searchItems = (alempi, ylempi) => {
  if (alempi === '' && ylempi === '') {return}
  anna alue
  if (alempi! == '' && ylempi! == '') {
    alue = IDBKeyRange.sidottu (alempi, ylempi)
  } else if (alempi === '') {
    alue = IDBKeyRange.upperBound (ylempi)
  } muuta {
    alue = IDBKeyRange.lowerBound (alempi)
  }
  dbPromise.then ((db) => {
    const tx = db.transaction (['koirat'], 'vain luku')
    const store = tx.objectStore ('koirat')
    const index = store.index ('ikä')
    palauta index.openCursor (alue)
  })
  . sitten (toiminto showRange (kohdistin) {
    if (! kohdistin) {return}
    console.log ('kohdistin on:', kohdistin.avain)
    for (const-kenttä kohdistimen arvossa) {
      console.log (cursor.value [kenttä])
    }
    palauta kohdistin. jatka (). sitten (showRange)
  })
  . sitten (() => {
    console.log ( 'tehty!')
  })
}
hakuKoiratBetweenAges (3, 10)
Haluatko oppia JavaScriptiä? Hanki ilmainen e-kirjani osoitteesta jshandbook.com