En esta guía, se tratan los aspectos básicos
API de IndexedDB.
Usamos la serie de Jake Archibald
IndexedDB prometido
muy similar a la API de IndexedDB, pero usa promesas, que
puedes await
para una sintaxis más concisa. Esto simplifica la API mientras
y mantener su estructura.
¿Qué es IndexedDB?
IndexedDB es un sistema de almacenamiento NoSQL a gran escala que permite almacenar sobre cualquier elemento en el navegador del usuario. Además de los métodos de búsqueda habituales, putt de acciones, IndexedDB también admite transacciones y es adecuado para para almacenar grandes cantidades de datos estructurados.
Cada base de datos IndexedDB es única para un origen. (por lo general, el dominio o subdominio del sitio), lo que significa que no se puede acceder al sitio de cualquier otro origen. Sus límites de almacenamiento de datos suelen ser grandes (en caso de que existan), pero distintos navegadores controlan los límites y la expulsión de datos de manera diferente. Consulta la sección Lecturas adicionales para obtener más información.
Términos de IndexedDB
- Base de datos
- Es el nivel más alto de IndexedDB. Contiene los almacenes de objetos que, a su vez, contienen los datos que deseas conservar. Puedes crear múltiples bases de datos con los nombres que elijas.
- Almacén de objetos
- Un bucket individual para almacenar datos, similar a las tablas de las bases de datos relacionales.
Por lo general, hay un depósito de objetos para cada tipo (no datos de JavaScript).
de los datos que almacenas. A diferencia de las tablas de bases de datos, los datos de JavaScript
tipos de datos en una tienda no necesitan ser coherentes. Por ejemplo, si una aplicación
tiene un almacén de objetos
people
que contiene información sobre tres personas, esas las propiedades de la edad de las personas podrían ser53
,'twenty-five'
yunknown
. - Índice
- Es un tipo de almacén de objetos para organizar datos en otro almacén de objetos (denominado un almacén de objetos de referencia) por una propiedad individual de los datos. El índice se usa para recuperar registros en el almacén de objetos mediante esta propiedad. Por ejemplo, si estás almacenando personas. Es posible que quieras buscarlas más tarde por su nombre, edad o animal favorito.
- Operación
- Una interacción con la base de datos.
- Transacción
- Wrapper de una operación o grupo de operaciones que garantiza que la base de datos para mantener la integridad de tus datos. Si una de las acciones en una transacción falla, ninguna de ellas se aplicada y la base de datos vuelve al estado en el que estaba antes de la transacción comenzó. Todas las operaciones de lectura o escritura en IndexedDB deben ser parte de una transacción. Esto permite operaciones atómicas de lectura, modificación y escritura sin riesgo de conflictos. mientras que otros subprocesos actúan en la base de datos al mismo tiempo.
- Cursor
- Es un mecanismo para iterar en varios registros de una base de datos.
Cómo verificar la compatibilidad con IndexedDB
IndexedDB es casi compatible con todos los usuarios.
Sin embargo, si trabajas con navegadores más antiguos, no es una mala idea
para detectar atributos por si acaso. La forma más fácil es verificar el window
objeto:
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();
Cómo abrir una base de datos
Con IndexedDB, puedes crear varias bases de datos con el nombre que elijas. Si
una base de datos no existe cuando intentas abrirla, se crean automáticamente.
Para abrir una base de datos, usa el método openDB()
de la biblioteca 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();
Este método muestra una promesa que se resuelve en un objeto de base de datos. Cuando uses
openDB()
, proporciona un nombre, un número de versión y un objeto de eventos para establecer
para configurar la base de datos.
Este es un ejemplo del método openDB()
en contexto:
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();
Coloca la verificación de compatibilidad con IndexedDB en la parte superior de la función anónima. Esta
sale de la función si el navegador no admite IndexedDB. Si la función puede
continuar, llama al método openDB()
para abrir una base de datos llamada 'test-db1'
.
En este ejemplo, el objeto de eventos opcional se excluyó para mantener las cosas
simple, pero debes especificarlo
para que realice un trabajo significativo con IndexedDB.
Cómo trabajar con almacenes de objetos
Una base de datos IndexedDB contiene uno o más almacenes de objetos, y cada uno tiene un una columna para una clave y otra para los datos asociados con esa clave.
Crea almacenes de objetos
Una base de datos IndexedDB bien estructurada debe tener un almacén de objetos para cada tipo
de datos que deben ser persistentes. Por ejemplo, en un sitio que conserva las credenciales
los perfiles y las notas pueden tener un almacén de objetos people
que contiene person
objetos, y un almacén de objetos notes
que contiene objetos note
.
Para garantizar la integridad de la base de datos, solo puedes crear o quitar almacenes de objetos en
eventos en una llamada a openDB()
. El objeto de eventos expone un upgrade()
.
que te permite crear almacenes de objetos. Llama al
createObjectStore()
dentro del método upgrade()
para crear el almacén de objetos:
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();
Este método toma el nombre del almacén de objetos y una configuración opcional que te permite definir varias propiedades para el almacén de objetos.
El siguiente es un ejemplo de cómo usar 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();
En este ejemplo, se pasa un objeto de eventos al método openDB()
para crear
el almacén de objetos y, como antes, se completa el trabajo de crearlo
en el método upgrade()
del objeto de evento. Sin embargo, como el navegador genera una
si intentas crear un almacén de objetos que ya existe, te recomendamos
uniendo el método createObjectStore()
en una sentencia if
que verifique
si el almacén de objetos existe. Dentro del bloque if
, llama a
createObjectStore()
para crear un almacén de objetos llamado 'firstOS'
.
Cómo definir claves primarias
Al definir almacenes de objetos, puedes definir cómo se identifican los datos de forma única en a la tienda usando una clave primaria. Para definir una clave primaria, puedes definir un con la ruta de acceso de la clave o con un generador de claves.
Una ruta de la clave es una propiedad que siempre existe y contiene un valor único. Para
Por ejemplo, en el caso de un almacén de objetos people
, puedes elegir el correo electrónico
como la ruta de acceso de la clave:
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();
En este ejemplo, se crea un almacén de objetos llamado 'people'
y se asigna el email
como clave primaria en la opción keyPath
.
También puedes usar un generador de claves, como autoIncrement
. El generador de claves
crea un valor único para cada objeto que se agrega al almacén de objetos. De forma predeterminada,
Si no especificas una clave, IndexedDB crea una clave y la almacena por separado.
de los datos.
En el siguiente ejemplo, se crea un almacén de objetos llamado 'notes'
y se establece la
la clave primaria se asignará automáticamente como un número de incremento automático:
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();
El siguiente ejemplo es similar al ejemplo anterior, pero esta vez
el valor de incremento automático se asigna de forma explícita a una propiedad llamada '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();
Elegir el método que se usará para definir la clave depende de tus datos. Si el
datos tienen una propiedad que siempre es única, puedes hacer que sea la keyPath
aplicar esta singularidad. De lo contrario, usa un valor de incremento automático.
El siguiente código crea tres almacenes de objetos que demuestran las distintas formas de definir las claves primarias en almacenes de objetos:
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();
Cómo definir índices
Los índices son un tipo de almacén de objetos que se usa para recuperar datos de la referencia de objetos de una propiedad especificada. Un índice reside dentro del objeto de referencia y contiene los mismos datos, pero usa la propiedad especificada como su la ruta de acceso de la clave en lugar de la clave primaria del almacén de referencia. Los índices deben hacerse cuando crea tus almacenes de objetos y se puede usar para definir una restricción única en tus datos.
Para crear un índice, llama a createIndex()
.
en una instancia de almacén de objetos:
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();
Este método crea y muestra un objeto de índice. El método createIndex()
en
la instancia del almacén de objetos toma el nombre del índice nuevo como el primer
El segundo argumento se refiere a la propiedad de los datos que quieres
índice. El argumento final te permite definir dos opciones que determinan cómo
opera el siguiente índice: unique
y multiEntry
. Si unique
se configura como true
,
no permite valores duplicados para una sola clave. A continuación, multiEntry
Determina cómo se comporta createIndex()
cuando la propiedad indexada es un array. Si
se establece en true
, createIndex()
agrega una entrada en el índice para cada array
. De lo contrario, agrega una sola entrada que contiene el array.
Por ejemplo:
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();
En este ejemplo, los almacenes de objetos 'people'
y 'notes'
tienen índices. Para
crea los índices, primero asigna el resultado de createObjectStore()
(un objeto
store) a una variable para que puedas llamar a createIndex()
en ella.
Cómo trabajar con datos
En esta sección, se describe cómo crear, leer, actualizar y borrar datos. Estos
las operaciones son todas asíncronas, con promesas en las que la API de IndexedDB usa
solicitudes. Esto simplifica la API. En lugar de detectar los eventos activados por
la solicitud, puedes llamar a .then()
en el objeto de la base de datos que muestra
Método openDB()
para iniciar interacciones con la base de datos, o await
su
de la creación de cuentas de servicio.
Todas las operaciones de datos en IndexedDB se llevan a cabo dentro de una transacción. Cada El formato es el siguiente:
- Obtén un objeto de base de datos.
- Transacción abierta en la base de datos.
- Abrir el depósito de objetos en la transacción
- Realizar la operación en el almacén de objetos
Una transacción puede considerarse como un wrapper seguro en torno a una operación o grupo de las operaciones. Si una de las acciones de una transacción falla, todas las acciones se revierten. Las transacciones son específicas de uno o más almacenes de objetos que defines cuando abres la transacción. Pueden ser de solo lectura o de lectura y escribir. Esto indica si las operaciones dentro de la transacción leen el datos o hacer cambios en la base de datos.
Crea datos
Para crear datos, llama a add()
.
en la instancia de base de datos y pasa los datos que desees agregar. El add()
El primer argumento de este método es el almacén de objetos al que quieres agregar los datos.
El segundo argumento es un objeto que contiene los campos y los datos asociados que quieres
para agregar. Este es el ejemplo más simple, en el que se agrega una sola fila de datos:
import {openDB} from 'idb';
async function addItemToStore () {
const db = await openDB('example-database', 1);
await db.add('storeName', {
field: 'data'
});
}
addItemToStore();
Cada llamada a add()
ocurre dentro de una transacción, de modo que incluso si se resuelve la promesa
con éxito, no significa necesariamente que la operación funcionó. Para asegurarte
se realizó la operación de adición, debes verificar si
se completó la transacción con el método transaction.done()
. Este es un
prometida que se resuelve cuando la transacción se completa por sí misma, y se rechaza si
errores de transacción. Debes realizar esta comprobación para toda la “escritura” operaciones,
porque es la única forma de saber
que los cambios en la base de datos
de que ocurra.
En el siguiente código, se muestra el uso del método add()
dentro de una transacción:
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();
Cuando abras la base de datos (y crees un almacén de objetos si es necesario), necesitarás
Para abrir una transacción, llama al método transaction()
. Este método
toma un argumento para la tienda en la que quiere realizar la transacción, además del modo.
En este caso, queremos escribirle a la tienda. En este ejemplo,
especifica 'readwrite'
.
El siguiente paso es comenzar a agregar artículos a la tienda como parte de la transacción.
En el ejemplo anterior, tratamos con tres operaciones en 'foods'
almacenar que cada una muestra una promesa:
- Agrega un récord para un sándwich sabroso.
- Se está agregando el registro de algunos huevos.
- Indica que se completó la transacción (
tx.done
).
Debido a que todas estas acciones se basan en promesas, debemos esperar a que
para que terminen. Pasar estas promesas a
Promise.all
es una forma cómoda y ergonómica de hacer esto. Promise.all
acepta un array de
promete y finaliza cuando se resuelven todas las promesas que se le pasa.
Para los dos registros que se agregan, la interfaz store
de la instancia de transacción
llama a add()
y le pasa los datos. Puedes await
la llamada de Promise.all
para que termine cuando se complete la transacción.
Lee datos
Para leer datos, llama a get()
.
en la instancia de base de datos que recuperas con el método openDB()
.
get()
toma el nombre de la tienda y el valor de clave primaria del objeto que
deseas recuperar. A continuación, te mostramos un ejemplo básico:
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();
Al igual que con add()
, el método get()
muestra una promesa, por lo que puedes await
si
que prefieras, o usa la devolución de llamada .then()
de la promesa.
En el siguiente ejemplo, se usa el método get()
en la base de datos 'test-db4'
Un almacén de objetos 'foods'
para obtener una sola fila por la clave primaria '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();
Recuperar una sola fila de la base de datos es bastante sencillo: open
a la base de datos y especifica el almacén de objetos y el valor de clave primaria de la fila
de las que quieres obtener datos. Debido a que el método get()
muestra una promesa, puedes
await
.
Cómo actualizar datos
Para actualizar los datos, llama a put()
.
en el almacén de objetos. El método put()
es similar al método add()
y también se puede usar en lugar de add()
para crear datos. Este es un ejemplo básico
del uso de put()
para actualizar una fila en un almacén de objetos según su valor de clave primaria:
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();
Al igual que otros métodos, este muestra una promesa. También puedes usar put()
como
parte de una transacción. Este es un ejemplo que usa la tienda 'foods'
anterior
que actualiza el precio del sándwich y los huevos:
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();
La forma en que se actualizan los elementos depende de cómo estableces una clave. Si estableces un keyPath
,
Cada fila del almacén de objetos está asociada con una clave de intercalado. La anterior
ejemplo actualiza las filas en función de esta clave y, cuando actualizas las filas de esta
actual, deberás especificar esa clave para actualizar el elemento apropiado en la
de un almacén de objetos. También puedes crear una clave fuera de línea estableciendo un
autoIncrement
como clave primaria
Borra datos
Para borrar datos, llama a delete()
.
en el almacén de objetos:
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();
Al igual que add()
y put()
, puedes usar esto como parte de una transacción:
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();
La estructura de la interacción de la base de datos es la misma que la del otro
las operaciones. Recuerda verificar que toda la transacción se haya completado antes del
incluido el método tx.done
en el array que pasas a Promise.all
.
Obteniendo todos los datos
Hasta ahora, solo recuperaste objetos de la tienda uno a la vez. También puedes
recuperar todos los datos, o un subconjunto, de un almacén de objetos o índice con
el método getAll()
o los cursores
El método getAll()
La forma más sencilla de recuperar todos los datos de un almacén de objetos es llamar a getAll()
en el almacén de objetos o índice de la siguiente manera:
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();
Este método muestra todos los objetos del almacén de objetos, sin restricciones. en absoluto. Es la forma más directa de obtener todos los valores de un almacén de objetos pero también la menos flexible.
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();
En este ejemplo, se llama a getAll()
en el almacén de objetos 'foods'
. Esto devuelve todos
los objetos de 'foods'
, ordenados según la clave primaria
Cómo usar los cursores
Los cursores son una forma más flexible de recuperar múltiples objetos. Un cursor selecciona cada objeto en un índice o almacén de objetos, uno por uno, lo que te permite hacer algo con los datos cuando se seleccionen. Los cursores, como las otras operaciones de base de datos, funcionan en las transacciones.
Para crear un cursor, llama a openCursor()
.
en el almacén de objetos como parte de una transacción. Usando la tienda 'foods'
de
ejemplos anteriores, esta es la manera de hacer avanzar un cursor por todas las filas de datos en
en un almacén de objetos:
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();
En este caso, la transacción se abre en modo 'readonly'
, y su
openCursor
. En un bucle while
posterior, la fila en el
la posición actual del cursor puede hacer que se lean las propiedades key
y value
, y
puede operar con esos valores de la manera que le resulte más conveniente para su
. Cuando esté todo listo, puedes llamar al continue()
del objeto cursor
.
método para ir a la siguiente fila, y el bucle while
termina cuando el cursor
llega al final del conjunto de datos.
Usa cursores con índices y rangos
Los índices te permiten recuperar los datos en un depósito de objetos de una propiedad que no sea la
clave primaria. Puedes crear un índice en cualquier propiedad, que se convierte en keyPath
.
para el índice, especificar un rango en esa propiedad y obtener los datos dentro del
rango usando getAll()
o un cursor.
Define tu rango con el objeto IDBKeyRange
. y cualquiera de los siguientes
métodos:
upperBound()
.lowerBound()
.bound()
(que es ambos):only()
.includes()
.
Los métodos upperBound()
y lowerBound()
especifican los límites inferior y superior
del rango.
IDBKeyRange.lowerBound(indexKey);
o:
IDBKeyRange.upperBound(indexKey);
Cada una toma un argumento: el valor keyPath
del índice para el elemento que deseas.
especificar como el límite superior o inferior.
El método bound()
especifica un límite inferior y superior:
IDBKeyRange.bound(lowerIndexKey, upperIndexKey);
El rango de estas funciones es inclusivo de forma predeterminada, lo que significa que incluye
los datos que se especifican como los límites del rango. Para omitir esos valores,
especifica el rango como exclusivo pasando true
como el segundo argumento para
lowerBound()
o upperBound()
, o como el tercer y cuarto argumento de
bound()
, para los límites inferior y superior, respectivamente.
En el siguiente ejemplo, se usa un índice en la propiedad 'price'
del objeto 'foods'
en una tienda física. Ahora, la tienda tiene un formulario adjunto con dos entradas para el
límites superior e inferior del rango. Usa el siguiente código para encontrar alimentos con
entre estos límites:
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);
El código de ejemplo primero obtiene los valores de los límites y comprueba si estos
existen. El siguiente bloque de código decide qué método usar para limitar el rango
según los valores. En la interacción de la base de datos, abre el almacén de objetos en
como de costumbre y, luego, abre el índice 'price'
en el almacén de objetos. El
El índice 'price'
te permite buscar artículos por precio.
Luego, el código abre un cursor en el índice y pasa el rango. El cursor
devuelve una promesa que representa el primer objeto en el rango, o undefined
si
no hay datos dentro del rango. El método cursor.continue()
devuelve un
que representa el siguiente objeto y continúa en el bucle hasta que
llegar al final del rango.
Control de versiones de bases de datos
Cuando llamas al método openDB()
, puedes especificar el número de versión de la base de datos.
en el segundo parámetro. En todos los ejemplos de esta guía, la versión se
configurado en 1
, pero una base de datos se puede actualizar a una versión nueva si lo necesitas
modificarlo de alguna manera. Si la versión especificada es superior a la versión de
la base de datos existente, se ejecuta la devolución de llamada upgrade
en el objeto de evento
lo que te permite agregar nuevos índices y almacenes de objetos a la base de datos.
El objeto db
en la devolución de llamada upgrade
tiene una propiedad oldVersion
especial.
que indica el número de versión de la base de datos a la que tiene acceso el navegador.
Puedes pasar este número de versión a una sentencia switch
para ejecutar bloques de
Código dentro de la devolución de llamada upgrade
según la versión de la base de datos existente
de la fila. Por ejemplo:
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');
}
}
});
En este ejemplo, se establece la versión más reciente de la base de datos en 2
. Cuando este código
se ejecuta primero, la base de datos aún no existe en el navegador, por lo que oldVersion
es 0
, y la sentencia switch
comienza en case 0
. En el ejemplo, esta
Agrega un almacén de objetos 'store'
a la base de datos.
Punto clave: En las sentencias switch
, suele haber un break
después de cada case
pero esto no se usa aquí deliberadamente. De esta manera, si el estado
base de datos tiene algunas versiones anteriores o, si no existe, el código continúa
por el resto de los bloques case
hasta que esté actualizado. En el ejemplo,
El navegador continúa ejecutándose a través de case 1
, lo que crea un índice name
en el
Almacén de objetos store
.
Para crear un índice 'description'
en el almacén de objetos 'store'
, actualiza el archivo
número de versión y agrega un nuevo bloque case
de la siguiente manera:
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');
}
}
});
Si la base de datos que creaste en el ejemplo anterior aún existe en el navegador,
Cuando se ejecuta, oldVersion
es 2
. El navegador omite case 0
y
case 1
y ejecuta el código en case 2
, que crea un description
índice. Después de eso, el navegador tendrá una base de datos en la versión 3 que contiene un store
.
un almacén de objetos con índices name
y description
.
Lecturas adicionales
Los siguientes recursos proporcionan más información y contexto para usar IndexedDB.
Documentación de IndexedDB
- Repositorio de GitHub de
idb
- Usa IndexedDB
- Conceptos básicos detrás de IndexedDB
- Especificación de la API de Indexed Database 3.0