Ten przewodnik zawiera podstawowe informacje
Interfejs API IndexedDB.
Mamy film Jake'a Archibalda
Obiekt IndexedDB jest obiecujący
która jest bardzo podobna do interfejsu IndexedDB API, ale korzysta z obietnic, które
możesz użyć funkcji await
, aby uzyskać bardziej zwięzłą składnię. Upraszcza to interfejs API, ale
na utrzymanie jego struktury.
Co to jest IndexedDB?
IndexedDB to wielkoskalowy system przechowywania danych NoSQL, który pozwala przechowywać do wszystkiego. Oprócz zwykłego wyszukiwania, otrzymasz oraz działania, IndexedDB obsługuje też transakcje. przechowywania dużych ilości uporządkowanych danych.
Każda baza danych IndexedDB jest unikalna dla źródła (zwykle jest to domena witryny lub subdomena), co oznacza, że witryna nie ma dostępu do witryny lub nie można uzyskać do niej dostępu. z jakiegokolwiek innego źródła. limity przechowywania danych, są zwykle duże, o ile w ogóle istnieją, ale różne przeglądarki obsługują ograniczenia i usuwania danych w inny sposób. W sekcji Więcej informacji znajdziesz znajdziesz więcej informacji.
Terminy dotyczące IndexedDB
- Baza danych
- Najwyższy poziom IndexedDB. Zawiera magazyny obiektów, które z kolei zawierają dane, które chcesz zachować. Możesz utworzyć wiele baz danych za pomocą dowolne nazwy.
- Składnica obiektów
- Pojedynczy zasobnik do przechowywania danych, podobny do tabel w relacyjnych bazach danych.
Zwykle dla każdego typu jest 1 magazyn obiektów (nie dane JavaScriptu)
typ danych, które przechowujesz. W przeciwieństwie do tabel bazy danych dane JavaScript
typów danych w sklepie nie muszą być spójne. Jeśli na przykład aplikacja
zawiera magazyn obiektów
people
z informacjami o 3 osobach, właściwościami wieku użytkowników mogą być53
,'twenty-five'
iunknown
. - Indeks
- Rodzaj magazynu obiektów do porządkowania danych w innym magazynie obiektów odwołania do magazynu obiektów) według pojedynczej właściwości danych. Używany jest indeks. aby pobrać rekordy z magazynu obiektów przez tę właściwość. Jeśli na przykład jesteś zapisując dane osób, możesz pobrać je później według imienia i nazwiska, wieku lub ulubione zwierzę.
- Operacja
- Interakcja z bazą danych.
- Transakcja
- Kod wokół operacji lub grupy operacji, który zapewnia bazę danych uczciwości. Jeśli jedno z działań w ramach transakcji się nie powiedzie, żadne z nich nie zostanie została zastosowana, a baza danych wróci do stanu sprzed transakcji rozpoczęły się. Wszystkie operacje odczytu i zapisu w IndexedDB muszą być częścią transakcji. Umożliwia to niepodzielne operacje odczytu, modyfikacji i zapisu bez ryzyka konfliktów dzięki czemu inne wątki korzystają z bazy danych w tym samym czasie.
- Kursor
- Mechanizm iteracji wielu rekordów w bazie danych.
Jak sprawdzić obsługę IndexedDB
Technologia IndexedDB jest prawie powszechnie obsługiwana.
Jednak w przypadku pracy ze starszymi przeglądarkami nie jest dobrym pomysłem
na wszelki wypadek. Najłatwiej to sprawdzić window
obiekt:
function indexedDBStuff () {
// Check for IndexedDB support:
if (!('indexedDB' in window)) {
// Can't use IndexedDB
console.log("This browser doesn't support IndexedDB");
return;
} else {
// Do IndexedDB stuff here:
// ...
}
}
// Run IndexedDB code:
indexedDBStuff();
Jak otworzyć bazę danych
Dzięki IndexedDB możesz tworzyć wiele baz danych o dowolnych nazwach. Jeśli
Przy próbie otwarcia bazy danych nie istnieje, utworzona automatycznie.
Aby otworzyć bazę danych, użyj metody openDB()
z biblioteki idb
:
import {openDB} from 'idb';
async function useDB () {
// Returns a promise, which makes `idb` usable with async-await.
const dbPromise = await openDB('example-database', version, events);
}
useDB();
Ta metoda zwraca obietnicę zwracającą się do obiektu bazy danych. Jeśli korzystasz z metody
openDB()
, podaj nazwę, numer wersji i obiekt zdarzeń do ustawienia
do uruchomienia bazy danych.
Oto przykład metody openDB()
w kontekście:
import {openDB} from 'idb';
async function useDB () {
// Opens the first version of the 'test-db1' database.
// If the database does not exist, it will be created.
const dbPromise = await openDB('test-db1', 1);
}
useDB();
Umieść zaznaczenie obsługi IndexedDB na górze funkcji anonimowej. Ten
kończy funkcję, jeśli przeglądarka nie obsługuje IndexedDB. Jeśli funkcja może
kontynuuje, wywołuje metodę openDB()
, aby otworzyć bazę danych o nazwie 'test-db1'
.
W tym przykładzie opcjonalny obiekt zdarzeń został pominięty, aby zachować
jest prosta, ale trzeba ją określić, aby wykonywać dowolne czynności związane z bazą IndexedDB.
Korzystanie z magazynów obiektów
Baza danych IndexedDB zawiera co najmniej jeden magazyn obiektów, z których każdy ma kolumnę z kluczem, a drugą kolumnę z danymi powiązanymi z tym kluczem.
Tworzenie magazynów obiektów
Dobrze uporządkowana baza danych IndexedDB powinna mieć po 1 magazynie obiektów dla każdego typu
które trzeba utrwalić. Na przykład w witrynie, która utrzymuje użytkowników
profile i notatki mogą mieć magazyn obiektów people
zawierający obiekt person
i magazyn obiektów notes
z note
obiektami.
Aby zapewnić integralność bazy danych, możesz tworzyć i usuwać magazyny obiektów tylko w
zdarzenia w wywołaniu openDB()
. Obiekt zdarzeń ujawnia: upgrade()
która pozwala tworzyć magazyny obiektów. Wywołaj funkcję
createObjectStore()
wewnątrz metody upgrade()
, aby utworzyć magazyn obiektów:
import {openDB} from 'idb';
async function createStoreInDB () {
const dbPromise = await openDB('example-database', 1, {
upgrade (db) {
// Creates an object store:
db.createObjectStore('storeName', options);
}
});
}
createStoreInDB();
Ta metoda przyjmuje nazwę magazynu obiektów i opcjonalną konfigurację , który pozwala zdefiniować różne właściwości magazynu obiektów.
Oto przykład użycia atrybutu createObjectStore()
:
import {openDB} from 'idb';
async function createStoreInDB () {
const dbPromise = await openDB('test-db1', 1, {
upgrade (db) {
console.log('Creating a new object store...');
// Checks if the object store exists:
if (!db.objectStoreNames.contains('people')) {
// If the object store does not exist, create it:
db.createObjectStore('people');
}
}
});
}
createStoreInDB();
W tym przykładzie obiekt zdarzeń jest przekazywany do metody openDB()
w celu utworzenia
w magazynie obiektów i tak jak wcześniej, utworzenie magazynu obiektów jest zakończone
w metodzie upgrade()
obiektu zdarzenia. Ponieważ jednak przeglądarka przesyła
jeśli próbujesz utworzyć magazyn obiektów, który już istnieje, zalecamy
można umieścić metodę createObjectStore()
w instrukcji if
, która sprawdza,
sprawdzić, czy magazyn obiektów istnieje. W obrębie bloku if
wywołaj
createObjectStore()
, aby utworzyć magazyn obiektów o nazwie 'firstOS'
.
Jak zdefiniować klucze podstawowe
Definiując magazyny obiektów, możesz określić sposób jednoznacznego identyfikowania danych w w sklepie za pomocą klucza podstawowego. Klucz podstawowy możesz zdefiniować przez zdefiniowanie lub za pomocą generatora kluczy.
Ścieżka klucza to usługa, która zawsze istnieje i zawiera unikalną wartość. Dla:
w przypadku magazynu obiektów people
możesz wybrać adres e-mail,
jako ścieżki klucza:
import {openDB} from 'idb';
async function createStoreInDB () {
const dbPromise = await openDB('test-db2', 1, {
upgrade (db) {
if (!db.objectStoreNames.contains('people')) {
db.createObjectStore('people', { keyPath: 'email' });
}
}
});
}
createStoreInDB();
Ten przykład tworzy magazyn obiektów o nazwie 'people'
i przypisuje email
jako klucza podstawowego w opcji keyPath
.
Możesz też użyć generatora kluczy, takiego jak autoIncrement
. Generator kluczy
tworzy unikalną wartość dla każdego obiektu dodanego do magazynu obiektów. Domyślnie
Jeśli nie określisz klucza, IndexedDB utworzy klucz i będzie go przechowywać oddzielnie
danych.
Poniższy przykład tworzy magazyn obiektów o nazwie 'notes'
i ustawia
klucz podstawowy zostanie przypisany automatycznie jako numer automatycznie zwiększający wartość:
import {openDB} from 'idb';
async function createStoreInDB () {
const dbPromise = await openDB('test-db2', 1, {
upgrade (db) {
if (!db.objectStoreNames.contains('notes')) {
db.createObjectStore('notes', { autoIncrement: true });
}
}
});
}
createStoreInDB();
Poniższy przykład jest podobny do poprzedniego, ale tym razem
wartość automatycznego przyrostu jest jawnie przypisana do właściwości o nazwie 'id'
.
import {openDB} from 'idb';
async function createStoreInDB () {
const dbPromise = await openDB('test-db2', 1, {
upgrade (db) {
if (!db.objectStoreNames.contains('logs')) {
db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
}
}
});
}
createStoreInDB();
Wybór metody definiowania klucza zależy od Twoich danych. Jeśli
ma właściwość, która jest zawsze unikalna, możesz ustawić keyPath
egzekwować tę wyjątkowość. W przeciwnym razie użyj wartości automatycznego przyrostu.
Poniższy kod tworzy 3 magazyny obiektów demonstrujące różne sposoby definiując klucze podstawowe w magazynach obiektów:
import {openDB} from 'idb';
async function createStoresInDB () {
const dbPromise = await openDB('test-db2', 1, {
upgrade (db) {
if (!db.objectStoreNames.contains('people')) {
db.createObjectStore('people', { keyPath: 'email' });
}
if (!db.objectStoreNames.contains('notes')) {
db.createObjectStore('notes', { autoIncrement: true });
}
if (!db.objectStoreNames.contains('logs')) {
db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
}
}
});
}
createStoresInDB();
Jak zdefiniować indeksy
Indeksy to rodzaj magazynu obiektów używany do pobierania danych z odwołania magazyn obiektów według określonej właściwości. Indeks znajduje się wewnątrz obiektu referencyjnego przechowuje i zawiera te same dane, ale używa wskazanej właściwości jako ścieżki klucza zamiast klucza podstawowego magazynu odwołań. Indeksy należy tworzyć, gdy Twoich magazynów obiektów. Może służyć do zdefiniowania unikalnego ograniczenia danych.
Aby utworzyć indeks, wywołaj metodę createIndex()
.
w instancji magazynu obiektów:
import {openDB} from 'idb';
async function createIndexInStore() {
const dbPromise = await openDB('storeName', 1, {
upgrade (db) {
const objectStore = db.createObjectStore('storeName');
objectStore.createIndex('indexName', 'property', options);
}
});
}
createIndexInStore();
Ta metoda tworzy i zwraca obiekt indeksu. Metoda createIndex()
włączona
instancja magazynu obiektów przyjmuje nazwę nowego indeksu jako pierwszy
a drugi argument odnosi się do właściwości na danych, które chcesz
indeksu. Ostatni argument pozwala zdefiniować dwie opcje, które określają sposób
indeks to: unique
i multiEntry
. Jeśli unique
ma wartość true
, makro
Indeks nie zezwala na zduplikowane wartości jednego klucza. Dalej: multiEntry
określa działanie elementu createIndex()
, gdy zindeksowana właściwość jest tablicą. Jeśli
ma wartość true
, createIndex()
dodaje wpis w indeksie dla każdej tablicy
. W przeciwnym razie doda jeden wpis zawierający tablicę.
Oto przykład:
import {openDB} from 'idb';
async function createIndexesInStores () {
const dbPromise = await openDB('test-db3', 1, {
upgrade (db) {
if (!db.objectStoreNames.contains('people')) {
const peopleObjectStore = db.createObjectStore('people', { keyPath: 'email' });
peopleObjectStore.createIndex('gender', 'gender', { unique: false });
peopleObjectStore.createIndex('ssn', 'ssn', { unique: true });
}
if (!db.objectStoreNames.contains('notes')) {
const notesObjectStore = db.createObjectStore('notes', { autoIncrement: true });
notesObjectStore.createIndex('title', 'title', { unique: false });
}
if (!db.objectStoreNames.contains('logs')) {
const logsObjectStore = db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
}
}
});
}
createIndexesInStores();
W tym przykładzie magazyny obiektów 'people'
i 'notes'
mają indeksy. Do
utwórz indeksy, najpierw przypisz wynik funkcji createObjectStore()
(obiekt
Store obiektu) do zmiennej, aby można było wywołać z niej funkcję createIndex()
.
Jak pracować z danymi
Z tej sekcji dowiesz się, jak tworzyć, odczytywać, aktualizować i usuwać dane. Te
asynchroniczne operacje, z użyciem obietnic, w których interfejs IndexedDB API
żądań. Upraszcza to interfejs API. Zamiast nasłuchiwać zdarzeń wywoływanych przez
możesz wywołać funkcję .then()
na obiekcie bazy danych zwróconym przez
openDB()
, aby rozpocząć interakcje z bazą danych, lub await
jej
proces tworzenia.
Wszystkie operacje na danych w IndexedDB są wykonywane w ramach transakcji. Każdy ma taki format:
- Pobranie obiektu bazy danych.
- Otwórz transakcję w bazie danych.
- Otwórz magazyn obiektów w transakcji.
- Wykonaj operację na magazynie obiektów.
Transakcję można traktować jako bezpieczny kod wokół operacji lub grupy operacji. Jeśli jedno z działań w ramach transakcji się nie powiedzie, wszystkie czynności są wycofane. Transakcje są specyficzne dla co najmniej 1 magazynu obiektów, które są określane przy otwarciu transakcji. Mogą być dostępne tylko do odczytu lub tylko do odczytu. i zapis. Wskazuje, czy operacje w ramach transakcji odczytują lub wprowadzić zmiany w bazie danych.
Utwórz dane
Aby utworzyć dane, wywołaj metodę add()
w instancji bazy danych i prześlij dane, które chcesz dodać. add()
pierwszym argumentem jest magazyn obiektów, do którego chcesz dodać dane, a metoda
jest to obiekt zawierający pola i powiązane dane, które mają
dodać. Oto najprostszy przykład, w którym dodajesz jeden wiersz danych:
import {openDB} from 'idb';
async function addItemToStore () {
const db = await openDB('example-database', 1);
await db.add('storeName', {
field: 'data'
});
}
addItemToStore();
Każde wywołanie add()
jest realizowane w ramach transakcji, nawet jeśli obietnica zostanie zrealizowana
nie musi to oznaczać, że operacja się udała. Aby upewnić się,
operacji dodawania, musisz sprawdzić, czy cała
transakcja została ukończona przy użyciu metody transaction.done()
. To jest
obietnicę rozwiązania problemu w chwili zrealizowania transakcji i odrzucanie, jeśli
błędów transakcji. Musisz przeprowadzić tę kontrolę dla wszystkich żądań zapisu operacji,
bo jest to jedyny sposób, aby się dowiedzieć, jakie zmiany w bazie danych
miało miejsce.
Ten kod pokazuje użycie metody add()
w transakcji:
import {openDB} from 'idb';
async function addItemsToStore () {
const db = await openDB('test-db4', 1, {
upgrade (db) {
if (!db.objectStoreNames.contains('foods')) {
db.createObjectStore('foods', { keyPath: 'name' });
}
}
});
// Create a transaction on the 'foods' store in read/write mode:
const tx = db.transaction('foods', 'readwrite');
// Add multiple items to the 'foods' store in a single transaction:
await Promise.all([
tx.store.add({
name: 'Sandwich',
price: 4.99,
description: 'A very tasty sandwich!',
created: new Date().getTime(),
}),
tx.store.add({
name: 'Eggs',
price: 2.99,
description: 'Some nice eggs you can cook up!',
created: new Date().getTime(),
}),
tx.done
]);
}
addItemsToStore();
Po otwarciu bazy danych (i w razie potrzeby utworzenie magazynu obiektów)
aby otworzyć transakcję, wywołując w niej metodę transaction()
. Ta metoda
pobiera argument dla sklepu, w którym chcesz dokonać transakcji, oraz tryb.
W tym przypadku chcemy napisać do sklepu, więc ten przykład
określa 'readwrite'
.
Następnym krokiem jest rozpoczęcie dodawania produktów do sklepu w ramach transakcji.
W poprzednim przykładzie mamy do czynienia z 3 operacjami na 'foods'
które zwracają obietnicę:
- Dodaję rekord pysznej kanapki.
- Dodaję rekord niektórych jajek.
- Informacja, że transakcja została zrealizowana (
tx.done
).
Wszystkie te działania opierają się na obietnicach, musimy więc poczekać, aż
aby je dokończyć. Spełnienie tych obietnic
Promise.all
to przyjemny, ergonomiczny sposób. Promise.all
akceptuje tablicę
obiecuje i kończy, gdy wszystkie obietnice jej partnera zostaną spełnione.
W przypadku 2 dodawanych rekordów interfejs store
instancji transakcji
wywołuje metodę add()
i przekazuje do niej dane. Możesz await
wykonać połączenie typu Promise.all
aby sfinalizować transakcję po jej sfinalizowaniu.
Odczytywanie danych
Aby odczytać dane, wywołaj metodę get()
w instancji bazy danych pobieranej przy użyciu metody openDB()
.
get()
przyjmuje nazwę magazynu i wartość klucza podstawowego obiektu, który
które chcesz pobrać. Oto podstawowy przykład:
import {openDB} from 'idb';
async function getItemFromStore () {
const db = await openDB('example-database', 1);
// Get a value from the object store by its primary key value:
const value = await db.get('storeName', 'unique-primary-key-value');
}
getItemFromStore();
Tak jak add()
, metoda get()
zwraca obietnicę, więc możesz ją await
, jeśli
wolisz, lub skorzystaj z wywołania zwrotnego .then()
obietnicy.
Poniższy przykład pokazuje użycie metody get()
w bazie danych 'test-db4'
'foods'
– magazyn obiektów, aby uzyskać pojedynczy wiersz według klucza podstawowego 'name'
:
import {openDB} from 'idb';
async function getItemFromStore () {
const db = await openDB('test-db4', 1);
const value = await db.get('foods', 'Sandwich');
console.dir(value);
}
getItemFromStore();
Pobieranie jednego wiersza z bazy danych jest dość proste: otwórz
bazy danych i określ magazyn obiektów oraz wartość klucza podstawowego dla wiersza,
z których chcesz uzyskać dane. Metoda get()
zwraca obietnicę, więc możesz
await
.
Zaktualizuj dane
Aby zaktualizować dane, wywołaj put()
w magazynie obiektów. Metoda put()
jest podobna do metody add()
, a także może być używany zamiast add()
do tworzenia danych. Oto podstawowy przykład
użycia funkcji put()
do aktualizacji wiersza w magazynie obiektów o jej wartość klucza podstawowego:
import {openDB} from 'idb';
async function updateItemInStore () {
const db = await openDB('example-database', 1);
// Update a value from in an object store with an inline key:
await db.put('storeName', { inlineKeyName: 'newValue' });
// Update a value from in an object store with an out-of-line key.
// In this case, the out-of-line key value is 1, which is the
// auto-incremented value.
await db.put('otherStoreName', { field: 'value' }, 1);
}
updateItemInStore();
Podobnie jak inne metody, ta metoda zwraca obietnicę. Możesz też użyć put()
jako
która stanowi część transakcji. Oto przykład z wykorzystaniem sklepu 'foods'
z wcześniejszego okresu
która aktualizuje cenę kanapki i jajek:
import {openDB} from 'idb';
async function updateItemsInStore () {
const db = await openDB('test-db4', 1);
// Create a transaction on the 'foods' store in read/write mode:
const tx = db.transaction('foods', 'readwrite');
// Update multiple items in the 'foods' store in a single transaction:
await Promise.all([
tx.store.put({
name: 'Sandwich',
price: 5.99,
description: 'A MORE tasty sandwich!',
updated: new Date().getTime() // This creates a new field
}),
tx.store.put({
name: 'Eggs',
price: 3.99,
description: 'Some even NICER eggs you can cook up!',
updated: new Date().getTime() // This creates a new field
}),
tx.done
]);
}
updateItemsInStore();
Sposób aktualizowania elementów zależy od tego, jak skonfigurujesz klucz. Jeśli ustawisz keyPath
,
każdy wiersz w magazynie obiektów jest powiązany z kluczem wbudowanym. Poprzednie
aktualizuje wiersze na podstawie tego klucza, a gdy zaktualizujesz wiersze w tym kluczu,
musisz podać ten klucz, aby zaktualizować odpowiedni element w
obiektami pamięci masowej. Możesz też utworzyć klucz zewnętrzny, ustawiając klucz
autoIncrement
jako klucz podstawowy.
Usuń dane
Aby usunąć dane, wywołaj delete()
w magazynie obiektów:
import {openDB} from 'idb';
async function deleteItemFromStore () {
const db = await openDB('example-database', 1);
// Delete a value
await db.delete('storeName', 'primary-key-value');
}
deleteItemFromStore();
Tak jak w przypadku usług add()
i put()
, w ramach transakcji możesz użyć tych informacji:
import {openDB} from 'idb';
async function deleteItemsFromStore () {
const db = await openDB('test-db4', 1);
// Create a transaction on the 'foods' store in read/write mode:
const tx = db.transaction('foods', 'readwrite');
// Delete multiple items from the 'foods' store in a single transaction:
await Promise.all([
tx.store.delete('Sandwich'),
tx.store.delete('Eggs'),
tx.done
]);
}
deleteItemsFromStore();
Struktura interakcji z bazą danych jest taka sama jak w drugim
operacji. Pamiętaj, aby sprawdzić, czy cała transakcja została zrealizowana do
łącznie z metodą tx.done
w tablicy przekazywanej do funkcji Promise.all
.
Pobieram wszystkie dane
Do tej pory obiekty ze sklepu zostały pobrane tylko pojedynczo. Możesz też
pobierz wszystkie dane lub ich podzbiór z magazynu lub indeksu obiektów za pomocą
za pomocą metody getAll()
albo kursorów.
Metoda getAll()
Najprostszym sposobem na pobranie wszystkich danych magazynu obiektów jest wywołanie metody getAll()
w magazynie obiektów lub indeksie w ten sposób:
import {openDB} from 'idb';
async function getAllItemsFromStore () {
const db = await openDB('test-db4', 1);
// Get all values from the designated object store:
const allValues = await db.getAll('storeName');
console.dir(allValues);
}
getAllItemsFromStore();
Ta metoda zwraca wszystkie obiekty w magazynie obiektów bez ograniczeń . To najprostszy sposób pobierania wszystkich wartości z magazynu obiektów, ale też najmniej elastyczny.
import {openDB} from 'idb';
async function getAllItemsFromStore () {
const db = await openDB('test-db4', 1);
// Get all values from the designated object store:
const allValues = await db.getAll('foods');
console.dir(allValues);
}
getAllItemsFromStore();
W tym przykładzie wywołujemy funkcję getAll()
w magazynie obiektów 'foods'
. Powoduje to zwrócenie wszystkich
obiekty z 'foods'
w kolejności od klucza podstawowego.
Jak korzystać z kursorów
Kursory to bardziej elastyczny sposób na pobieranie wielu obiektów. Kursor wybiera każdy obiekt w magazynie obiektów lub indeksuj go jeden po drugim, dzięki czemu możesz z danymi po ich zaznaczeniu. Kursory, podobnie jak inne operacje na bazach danych, jak szacuje się ich liczba.
Aby utworzyć kursor, wywołaj openCursor()
.
w magazynie obiektów w ramach transakcji. Korzystam ze sklepu 'foods'
z
W poprzednich przykładach pokazujemy, jak przesunąć kursor po wszystkich wierszach danych w
magazyn obiektów:
import {openDB} from 'idb';
async function getAllItemsFromStoreWithCursor () {
const db = await openDB('test-db4', 1);
const tx = await db.transaction('foods', 'readonly');
// Open a cursor on the designated object store:
let cursor = await tx.store.openCursor();
// Iterate on the cursor, row by row:
while (cursor) {
// Show the data in the row at the current cursor position:
console.log(cursor.key, cursor.value);
// Advance the cursor to the next row:
cursor = await cursor.continue();
}
}
getAllItemsFromStoreWithCursor();
Transakcja w tym przypadku jest otwarta w trybie 'readonly'
, a jej
Wywoływana jest metoda openCursor
. W kolejnej pętli while
wiersz w
w przypadku bieżącej pozycji kursora można odczytać właściwości key
i value
oraz
Możesz operować na tych wartościach w dowolny sposób,
. Następnie możesz wywołać funkcję continue()
obiektu cursor
powoduje przejście do następnego wiersza, a pętla while
kończy się, gdy kursor
dotrze do końca zbioru danych.
Używanie kursorów z zakresami i indeksami
Indeksy umożliwiają pobieranie danych do magazynu obiektów przez właściwość inną niż
klucz podstawowy. Indeks możesz utworzyć dla dowolnej usługi, która stanie się domeną keyPath
dla indeksu, określ zakres tej właściwości i pobierz dane z
za pomocą getAll()
lub kursora.
Zdefiniuj zakres za pomocą obiektu IDBKeyRange
. i dowolny z tych elementów
metody:
upperBound()
.lowerBound()
.bound()
(czyli oba).only()
.includes()
.
Metody upperBound()
i lowerBound()
określają górne i dolne granice
w zakresie.
IDBKeyRange.lowerBound(indexKey);
Lub:
IDBKeyRange.upperBound(indexKey);
Każdy z nich przyjmuje po 1 argumencie: wartość keyPath
indeksu dla danego elementu
który określa górny lub dolny limit.
Metoda bound()
określa zarówno górny, jak i dolny limit:
IDBKeyRange.bound(lowerIndexKey, upperIndexKey);
Zakres tych funkcji jest domyślnie włącznie, co oznacza, że obejmuje m.in.
danych określonych jako granice zakresu. Aby wykluczyć te wartości,
określ zakres jako wyłączny, przekazując true
jako drugi argument funkcji
lowerBound()
lub upperBound()
albo jako trzeci i czwarty argument argumentu
bound()
odpowiednio dla dolnego i górnego limitu.
W następnym przykładzie użyto indeksu we właściwości 'price'
w obiekcie 'foods'
.
sklepu. Do sklepu jest teraz dołączony formularz z 2 wprowadzanymi w nim polami
górnej i dolnej granicy zakresu. Użyj następującego kodu, aby znaleźć produkty zawierające:
ceny między tymi limitami:
import {openDB} from 'idb';
async function searchItems (lower, upper) {
if (!lower === '' && upper === '') {
return;
}
let range;
if (lower !== '' && upper !== '') {
range = IDBKeyRange.bound(lower, upper);
} else if (lower === '') {
range = IDBKeyRange.upperBound(upper);
} else {
range = IDBKeyRange.lowerBound(lower);
}
const db = await openDB('test-db4', 1);
const tx = await db.transaction('foods', 'readonly');
const index = tx.store.index('price');
// Open a cursor on the designated object store:
let cursor = await index.openCursor(range);
if (!cursor) {
return;
}
// Iterate on the cursor, row by row:
while (cursor) {
// Show the data in the row at the current cursor position:
console.log(cursor.key, cursor.value);
// Advance the cursor to the next row:
cursor = await cursor.continue();
}
}
// Get items priced between one and four dollars:
searchItems(1.00, 4.00);
Przykładowy kod najpierw pobiera wartości limitów i sprawdza, czy limity
istnieje. Następny blok kodu określa metodę, której należy użyć do ograniczenia zakresu
na podstawie wartości. Podczas interakcji z bazą danych otwórz magazyn obiektów w
transakcji w zwykły sposób, a następnie otwórz indeks 'price'
w magazynie obiektów.
Indeks 'price'
umożliwia wyszukiwanie elementów według ceny.
Następnie kod otwiera kursor w indeksie i przekazuje w zakresie. Kursor
zwraca obietnicę reprezentującą pierwszy obiekt w zakresie lub undefined
, jeśli
w zakresie nie ma żadnych danych. Metoda cursor.continue()
zwraca błąd
kursora reprezentującego następny obiekt. Kontynuujemy pętlę do momentu,
osiągnie koniec zakresu.
Obsługa wersji bazy danych
Gdy wywołujesz metodę openDB()
, możesz podać numer wersji bazy danych
w drugim parametrze. We wszystkich przykładach w tym przewodniku wersja została
ma wartość 1
, ale w razie potrzeby bazę danych można uaktualnić do nowej wersji
w jakiś sposób go zmodyfikować. Jeśli podana wersja jest nowsza niż wersja
w istniejącej bazie danych wykonywane jest wywołanie zwrotne upgrade
w obiekcie zdarzenia,
co pozwala dodawać do bazy danych nowe magazyny obiektów i indeksy.
Obiekt db
w wywołaniu zwrotnym upgrade
ma specjalną właściwość oldVersion
,
, który wskazuje numer wersji bazy danych, do której ma dostęp przeglądarka.
Możesz przekazać ten numer wersji do instrukcji switch
, aby wykonywać bloki
kod w wywołaniu zwrotnym upgrade
na podstawie istniejącej wersji bazy danych
numer. Oto przykład:
import {openDB} from 'idb';
const db = await openDB('example-database', 2, {
upgrade (db, oldVersion) {
switch (oldVersion) {
case 0:
// Create first object store:
db.createObjectStore('store', { keyPath: 'name' });
case 1:
// Get the original object store, and create an index on it:
const tx = await db.transaction('store', 'readwrite');
tx.store.createIndex('name', 'name');
}
}
});
Ten przykład ustawia najnowszą wersję bazy danych na 2
. Gdy ten kod
bazy danych nie ma jeszcze w przeglądarce, więc oldVersion
to 0
, a instrukcja switch
zaczyna się od case 0
. W tym przykładzie
dodaje do bazy danych bazę obiektów 'store'
.
Ważne: w wyrażeniach switch
po każdym case
zwykle występuje break
ale celowo nie używa się go tutaj. Dzięki temu, jeśli występują
jest o kilka wersji wstecz, a jeśli baza danych nie istnieje, kod będzie kontynuowany
przez resztę case
blokad, aż zostanie zaktualizowana. W tym przykładzie
przeglądarka kontynuuje wykonywanie zadań przez interfejs case 1
, tworząc indeks name
w
Magazyn obiektów store
.
Aby utworzyć indeks 'description'
w magazynie obiektów 'store'
, zaktualizuj
wersji i dodaj nowy blok case
w następujący sposób:
import {openDB} from 'idb';
const db = await openDB('example-database', 3, {
upgrade (db, oldVersion) {
switch (oldVersion) {
case 0:
// Create first object store:
db.createObjectStore('store', { keyPath: 'name' });
case 1:
// Get the original object store, and create an index on it:
const tx = await db.transaction('store', 'readwrite');
tx.store.createIndex('name', 'name');
case 2:
const tx = await db.transaction('store', 'readwrite');
tx.store.createIndex('description', 'description');
}
}
});
Jeśli baza danych utworzona w poprzednim przykładzie nadal istnieje w przeglądarce,
po wykonaniu tego polecenia oldVersion
to 2
. Przeglądarka pomija case 0
i
case 1
i uruchamia kod w elemencie case 2
, co tworzy description
indeksu. Następnie przeglądarka korzysta z bazy danych w wersji 3 zawierającej tabelę store
magazyn obiektów z indeksami name
i description
.
Więcej informacji
Poniższe zasoby zawierają więcej informacji i zapewniają dodatkowe informacje o korzystaniu z IndexedDB.
Dokumentacja IndexedDB
idb
repozytorium GitHub- Korzystanie z IndexedDB
- Podstawowe pojęcia związane z technologią IndexedDB
- Specyfikacja interfejsu Indexed Database API 3.0