Kratki, ali cjeloviti vodič za IndexedDB i pohranu podataka u preglednike

Zanima vas učenje JavaScripta? Nabavite moju JavaScript e-knjigu na jshandbook.com

Uvod u IndexedDB

IndexedDB je jedna od mogućnosti pohrane koja je u preglednike uvedena tijekom godina.

To je spremište ključeva / vrijednosti (baza podataka noSQL) koje se smatra konačnim rješenjem za pohranu podataka u preglednike .

To je asinkroni API, što znači da izvođenje skupih operacija neće blokirati nit korisničkog sučelja pružajući traljavo iskustvo korisnicima. Može pohraniti neograničenu količinu podataka, iako jednom kada korisnik prijeđe određeni prag od korisnika se traži da web mjestu postavi veća ograničenja.

Podržana je u svim modernim preglednicima.

Podržava transakcije, izradu verzija i daje dobre performanse.

Unutar preglednika također možemo koristiti:

  • Kolačići : mogu ugostiti vrlo malu količinu nizova
  • Web Storage (ili DOM Storage), pojam koji obično identificira localStorage i sessionStorage, dvije trgovine ključeva / vrijednosti. sessionStorage, ne zadržava podatke, koji se brišu po završetku sesije, dok localStorage čuva podatke u svim sesijama

Lokalna pohrana / pohrana sesija ima nedostatak što je ograničena na malu (i nedosljednu) veličinu, a implementacija preglednika nudi od 2 MB do 10 MB prostora po web mjestu.

U prošlosti smo imali i Web SQL , omot oko SQLitea, ali sada je to zastarjelo i nije podržano u nekim modernim preglednicima, nikada nije bio priznati standard i zato se ne bi trebao koristiti, iako 83% korisnika ima ovu tehnologiju na svom uređaje prema Mogu li koristiti.

Iako tehnički možete stvoriti više baza podataka po web mjestu, u pravilu stvarate jednu bazu podataka , a unutar te baze podataka možete stvoriti više spremišta objekata .

Baza podataka je privatna za domenu , tako da bilo koja druga web lokacija ne može pristupiti drugoj web lokaciji IndexedDB trgovinama.

Svaka trgovina obično sadrži skup stvari koje mogu biti

  • žice
  • brojevi
  • predmeta
  • nizovi
  • datumi

Na primjer, možda imate trgovinu koja sadrži postove, drugu koja sadrži komentare.

Trgovina sadrži niz predmeta koji imaju jedinstveni ključ koji predstavlja način na koji se objekt može identificirati.

Te trgovine možete mijenjati pomoću transakcija izvršavanjem operacija dodavanja, uređivanja i brisanja i prevrtanjem stavki koje sadrže.

Od pojave Promisesa u ES6 i kasnijeg prelaska API-ja na korištenje obećanja, IndexedDB API izgleda pomalo stara škola .

Iako u tome nema ništa loše, u svim primjerima koje ću objasniti koristit ću IndexedDB Promised Library Jakea Archibalda, koji je sićušni sloj na vrhu IndexedDB API-ja radi lakšeg korištenja.

Ova se knjižnica također koristi na svim primjerima na web mjestu Google Developers u vezi s IndexedDB

Stvorite IndexedDB bazu podataka

Najjednostavniji način je koristiti unpkg , dodavanjem ovog u zaglavlje stranice:

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

Prije upotrebe IndexedDB API, uvijek provjerite ima li podrške u pregledniku, iako je široko dostupan, nikad ne znate koji preglednik korisnik koristi:

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

Kako stvoriti bazu podataka

Korištenje 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) } }) })() 

Prva 2 parametra su ime baze podataka i verzija. Treći parametar, koji nije obavezan, objekt je koji sadrži funkciju koja se poziva samo ako je broj verzije veći od trenutne instalirane verzije baze podataka . U tijelu funkcije možete nadograditi strukturu (pohrane i indekse) db-a.

Dodavanje podataka u trgovinu

Dodavanje podataka prilikom stvaranja spremišta, njihova inicijalizacija

Koristite putmetodu spremanja objekata, ali prvo trebamo referencu na nju iz koje možemo doći db.createObjectStore()kad je kreiramo.

Kada se koristi put, vrijednost je prvi argument, a ključ drugi. To je zato što ako navedete keyPathprilikom stvaranja spremišta objekata, ne trebate unositi ime ključa na svaki zahtjev put (), možete samo napisati vrijednost.

Ovo se popunjava store0čim ga kreiramo:

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

Dodavanje podataka kada je trgovina već kreirana, pomoću transakcija

Da biste kasnije dodali stavke, trebate stvoriti transakciju čitanja / pisanja , koja osigurava cjelovitost baze podataka (ako operacija ne uspije, sve operacije u transakciji se vraćaju i stanje se vraća u poznato stanje).

Za to upotrijebite referencu na dbPromiseobjekt koji smo dobili prilikom poziva openDBi pokrenite:

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

Dohvaćanje podataka iz trgovine

Preuzimanje jednog predmeta iz trgovine: get()

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

Preuzimanje svih predmeta iz trgovine: getAll()

Spremite sve ključeve

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

Spremite sve vrijednosti

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

Brisanje podataka iz IndexedDB

Brisanje baze podataka, spremišta objekata i podataka

Izbrišite cijelu bazu podataka IndexedDB

const dbName = 'mydbname' await deleteDB(dbName) 

Da biste izbrisali podatke u spremištu objekata

Koristimo transakciju:

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

Migracija s prethodne verzije baze podataka

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!

To su samo osnove. Nisam razgovarao o kursorima i naprednijim stvarima. IndexedDB ima još toga, ali nadam se da će vam ovo dati prednost.

Zanima vas učenje JavaScripta? Nabavite moju JavaScript knjigu na jshandbook.com