Trabajando con IndexedDB

Uno de los desarrollos más interesantes en los estándares web últimamente es la especificación de base de datos indexada (IndexedDB para abreviar). Para un momento divertido puede leer la especificación usted mismo. En este tutorial, explicaré esta función y, con suerte, te daré algo de inspiración para usar esta potente función..


Visión general

Como especificación, IndexedDB es actualmente una recomendación de candidato.

En pocas palabras, IndexedDB le proporciona una manera de almacenar grandes cantidades de datos en el navegador de su usuario. Cualquier aplicación que necesite enviar una gran cantidad de datos a través del cable podría beneficiarse enormemente de poder almacenar esos datos en el cliente. Por supuesto, el almacenamiento es sólo una parte de la ecuación. IndexedDB también proporciona una potente API de búsqueda basada en índices para recuperar los datos que necesita.

Puede preguntarse en qué se diferencian los IndexedDB de otros mecanismos de almacenamiento.?

Las cookies son extremadamente compatibles, pero tienen implicaciones legales y espacio de almacenamiento limitado. Además, se envían al servidor con cada solicitud, negando por completo los beneficios del almacenamiento del lado del cliente..

El almacenamiento local también está muy bien soportado, pero limitado en términos de la cantidad total de almacenamiento que puede utilizar. El almacenamiento local no proporciona una verdadera API de "búsqueda", ya que los datos solo se recuperan a través de valores clave. El almacenamiento local es excelente para cosas "específicas" que puede almacenar, por ejemplo, las preferencias, mientras que IndexedDB es más adecuado para datos Ad Hoc (como una base de datos).

Sin embargo, antes de seguir adelante, hablemos honestamente sobre el estado de IndexedDB en términos de compatibilidad con el navegador. Como especificación, IndexedDB es actualmente una recomendación de candidato. En este punto, la gente detrás de la especificación está contenta con eso, pero ahora está buscando comentarios de la comunidad de desarrolladores. La especificación puede cambiar entre la etapa actual y la final, Recomendación W3C. En general, los navegadores que admiten IndexedDB ahora lo hacen de una manera bastante consistente, pero los desarrolladores deben estar preparados para lidiar con los prefijos y tomar nota de las actualizaciones en el futuro.

En cuanto a los navegadores que admiten IndexedDB, tienes un poco de dilema. El soporte es bastante bueno para el escritorio, pero prácticamente no existe para dispositivos móviles. A ver que excelente sitio CanIUse.com dice:


Chrome para Android es compatible con la función, pero muy pocas personas actualmente usan ese navegador en dispositivos Android. ¿La falta de soporte móvil implica que no se debe usar? ¡Por supuesto no! Esperemos que todos nuestros lectores estén familiarizados con el concepto de mejora progresiva. Las características como IndexedDB se pueden agregar a su aplicación de una manera que no se interrumpa en los navegadores no compatibles. Puede usar bibliotecas de envoltorios para cambiar a WebSQL en dispositivos móviles o simplemente omitir el almacenamiento de datos localmente en sus clientes móviles. Personalmente, creo que la capacidad de almacenar grandes bloques de datos en el cliente es lo suficientemente importante como para usarlo ahora, incluso sin soporte móvil.


Empecemos

Hemos cubierto la especificación y el soporte, ahora veamos cómo usar la función. Lo primero que debemos hacer es verificar la compatibilidad con IndexedDB. Si bien existen herramientas que brindan formas genéricas de verificar las características del navegador, podemos simplificar esto ya que solo estamos comprobando una cosa en particular.

document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" en la ventana) console.log ("YES !!! I PUEDO HACERLO !!! WOOT !!!"); else console.log ("Tengo un triste.");, Falso);

El fragmento de código de arriba (disponible en test1.html si descarga el archivo zip adjunto a este artículo) utiliza el DOMContentLoaded evento para esperar a que la página se cargue. (Ok, eso es algo obvio, pero reconozco que esto puede no ser familiar para las personas que solo han usado jQuery). Luego simplemente veo si indexedDB existe en el ventana Objeto y si es así, estamos bien para ir. Ese es el ejemplo más simple, pero normalmente querríamos almacenar esto para saber más adelante si podemos usar la función. Aquí hay un ejemplo un poco más avanzado (test2.html).

var idbSupported = false; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" en la ventana) idbSupported = true;, false);

Todo lo que he hecho es crear una variable global., idbSupported, que se puede usar como una bandera para ver si el navegador actual puede usar IndexedDB.


Abrir una base de datos

IndexedDB, como puede imaginar, hace uso de bases de datos. Para ser claros, esto no es una implementación de SQL Server. Esta base de datos es local para el navegador y solo está disponible para el usuario. Las bases de datos de IndexedDB siguen las mismas reglas que las cookies y el almacenamiento local. Una base de datos es única para el dominio desde el que se cargó. Así, por ejemplo, una base de datos llamada "Foo" creada en foo.com no entrará en conflicto con una base de datos del mismo nombre en goo.com. No solo no entrará en conflicto, sino que no estará disponible para otros dominios. Puede almacenar datos para su sitio web sabiendo que otro sitio web no podrá acceder a él.

La apertura de una base de datos se realiza mediante el comando abrir. En el uso básico usted proporciona un nombre y una versión. La version es muy Importante por razones que cubriré más adelante. Aquí hay un ejemplo simple:

var openRequest = indexedDB.open ("test", 1);

Abrir una base de datos es una operación asíncrona. Para manejar el resultado de esta operación, deberá agregar algunos detectores de eventos. Hay cuatro tipos diferentes de eventos que pueden ser activados:

  • éxito
  • error
  • actualizado
  • obstruido

Probablemente puedas adivinar qué implican el éxito y el error. El evento actualizado se usa tanto cuando el usuario abre la base de datos por primera vez como cuando cambia la versión. El bloqueo no es algo que sucederá normalmente, pero puede dispararse si una conexión anterior nunca se cerró.

Por lo general, lo que debería suceder es que, en el primer golpe a su sitio, se activará el evento actualizado. Después de eso, sólo el controlador de éxito. Veamos un ejemplo simple (test3.html).

var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" en la ventana) idbSupported = true; if (idbSupported) var openRequest = indexedDB.open ("test", 1); openRequest.onupgradeneeded = function (e) console.log ("Actualizando ..."); openRequest.onsuccess = function (e) console.log ("Success!"); db = e.target.result; openRequest.onerror = function (e ) console.log ("Error"); console.dir (e);, false);

Una vez más, verificamos si IndexedDB es realmente compatible, y si lo es, abrimos una base de datos. Hemos cubierto tres eventos aquí: el evento de actualización necesaria, el evento de éxito y el evento de error. Por ahora centrarse en el evento de éxito. El evento se pasa un controlador a través de target.result. Hemos copiado eso a una variable global llamada db. Esto es algo que usaremos más adelante para agregar datos. Si ejecuta esto en su navegador (¡en uno que es compatible con IndexedDB por supuesto!), Debería ver el mensaje de actualización y éxito en su consola la primera vez que ejecute el script. La segunda vez, y así sucesivamente, cuando ejecute el script, solo debería ver el mensaje de éxito..


Tiendas de objetos

Hasta ahora, hemos comprobado la compatibilidad con IndexedDB, lo hemos confirmado y hemos abierto una conexión a una base de datos. Ahora necesitamos un lugar para almacenar datos. IndexedDB tiene un concepto de "Tiendas de objetos". Puede pensar en esto como una tabla de base de datos típica. (Es mucho más flexible que una tabla de base de datos típica, pero no se preocupe por eso ahora). Los almacenes de objetos tienen datos (obviamente) pero también una ruta de acceso clave y un conjunto opcional de índices. Los Keypaths son básicamente identificadores únicos para sus datos y vienen en varios formatos diferentes. Los índices se cubrirán más adelante cuando comencemos a hablar sobre la recuperación de datos.

Ahora por algo crucial. ¿Recuerdas el evento actualizado mencionado anteriormente? Solo puede crear almacenes de objetos durante un evento actualizado. Ahora, de forma predeterminada, se ejecutará automáticamente la primera vez que un usuario llegue a su sitio. Puedes usar esto para crear tus almacenes de objetos. Lo crucial para recordar es que si alguna vez necesita modificar Si almacena sus objetos, necesitará actualizar la versión (nuevamente en ese evento abierto) y escribir código para manejar sus cambios. Veamos un ejemplo simple de esto en acción..

var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" en la ventana) idbSupported = true; if (idbSupported) var openRequest = indexedDB.open ("test_v2", openRequest.onupgradeneded = (e) console.log ("ejecutando onupgradeneeded"); var thisDB = e.target.result; if (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS"); openRequest .onsuccess = función (e) console.log ("Success!"); db = e.target.result; openRequest.onerror = function (e) console.log ("Error"); console.dir (e );, falso);

Este ejemplo (test4.html) se basa en las entradas anteriores, así que me centraré en las novedades. Dentro del evento actualizado, he hecho uso de la variable de base de datos que se le ha pasado (este DB). Una de las propiedades de esta variable es una lista de almacenes de objetos existentes llamada objectStoreNames. Para la gente curiosa, esto no es una matriz simple sino una "DOMStringList". No me preguntes, pero ahí tienes. Podemos usar el contiene método para ver si nuestro almacén de objetos existe, y si no, créelo. Esta es una de las pocas funciones síncronas en IndexedDB, por lo que no tenemos que escuchar el resultado.

Para resumir entonces, esto es lo que sucedería cuando un usuario visita su sitio. La primera vez que están aquí, el evento actualizado se dispara. El código verifica si existe un almacén de objetos, "firstOS". No lo hará. Por lo tanto - se crea. Luego se ejecuta el controlador de éxito. La segunda vez que visiten el sitio, el número de versión será el mismo, por lo que el evento actualizado es no despedido.

Ahora imagine que desea agregar un segundo almacén de objetos. Todo lo que necesita hacer es incrementar el número de versión y, básicamente, duplicar el bloque de código contiene / createObjectStore que se ve arriba. Lo bueno es que su código actualizado admitirá tanto a las personas que son nuevas en el sitio como a las que ya tenían el primer almacén de objetos. Aquí hay un ejemplo de esto (test5.html):

var openRequest = indexedDB.open ("test_v2", 2); openRequest.onupgradeneeded = function (e) console.log ("ejecutando onupgradeneeded"); var thisDB = e.target.result; if (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS");  if (! thisDB.objectStoreNames.contains ("secondOS")) thisDB.createObjectStore ("secondOS"); 

Añadiendo datos

Una vez que tenga listos sus almacenes de objetos, puede comenzar a agregar datos. Este es, quizás, uno de los aspectos más geniales de IndexedDB. A diferencia de las bases de datos basadas en tablas tradicionales, IndexedDB le permite almacenar un objeto tal como está. Lo que eso significa es que puedes tomar un objeto genérico de JavaScript y simplemente almacenarlo. Hecho. Obviamente hay algunas advertencias aquí, pero en su mayor parte, eso es todo.

Trabajar con datos requiere que uses una transacción. Las transacciones toman dos argumentos. La primera es una serie de tablas con las que trabajarás. La mayoría de las veces esta será una mesa. El segundo argumento es el tipo de transacción. Hay dos tipos de transacciones: readonly y readwrite. Agregar datos será una operación de reescritura. Empecemos por crear la transacción:

// Supongamos que db es una variable de base de datos abierta anteriormente var transaction = db.transaction (["people"], "readwrite");

Tenga en cuenta que el almacén de objetos, "personas", es solo uno que hemos creado en el ejemplo anterior. Nuestra próxima demostración completa hará uso de ella. Después de obtener la transacción, pídale el almacén de objetos con el que dijo que trabajaría:

var store = transaction.objectStore ("personas");

Ahora que tienes la tienda puedes agregar datos. Esto se hace a través de la - espere por ello - añadir método.

// Defina una persona var person = nombre: nombre, correo electrónico: correo electrónico, creado: new Date () // Realice la solicitud add var = store.add (person, 1);

Recuerde que antes dijimos que puede almacenar cualquier información que desee (en su mayor parte). Así que mi persona objeto arriba es completamente arbitrario. Podría haber usado el nombre y el apellido en lugar de solo el nombre. Podría haber usado una propiedad de género. Tienes la idea El segundo argumento es la clave utilizada para identificar de forma única los datos. En este caso, lo hemos codificado en 1, lo que causará un problema bastante rápido. Eso está bien - aprenderemos cómo corregirlo.

La operación de adición es asíncrona, así que agreguemos dos controladores de eventos para el resultado.

request.onerror = function (e) console.log ("Error", e.target.error.name); // algún tipo de controlador de errores request.onsuccess = function (e) console.log ("Woot! Did it"); 

Tenemos un onerror manejador de errores y éxito Para buenos cambios. Bastante obvio, pero veamos un ejemplo completo. Puedes encontrar esto en el archivo. test6.html.

>
      

El ejemplo anterior contiene un formulario pequeño con un botón para activar un evento y almacenar los datos en IndexedDB. Ejecute esto en su navegador, agregue algo a los campos del formulario y haga clic en agregar. Si tiene abiertas las herramientas de desarrollo de su navegador, debería ver algo como esto.


Este es un buen momento para señalar que Chrome tiene un visor excelente para los datos de IndexedDB. Si hace clic en la pestaña Recursos, expande la sección IndexedDB, puede ver la base de datos creada por esta demostración, así como el objeto que acaba de ingresar..


Para mayor detalle, siga adelante y presione el botón Agregar datos nuevamente. Deberías ver un error en la consola:


El mensaje de error debe ser una pista. ConstraintError significa que solo intentamos agregar datos con la misma clave que ya existía. Si recuerdas, codificamos esa clave y sabía Eso iba a ser un problema. Es hora de hablar llaves.


Llaves

Las claves son la versión de las claves primarias de IndexedDB. Las bases de datos tradicionales pueden tener tablas sin claves, pero cada almacén de objetos debe tener una clave. IndexedDB permite un par de diferentes tipos de claves.

La primera opción es simplemente especificarlo usted mismo, como hicimos anteriormente. Podríamos usar la lógica para generar claves únicas..

Su segunda opción es una ruta de acceso clave, donde la clave se basa en una propiedad de los datos en sí. Considere el ejemplo de nuestra gente: podríamos usar una dirección de correo electrónico como clave.

Su tercera opción, y en mi opinión, la más sencilla, es utilizar un generador de claves. Esto funciona de manera muy parecida a una clave primaria autonumérica y es el método más simple para especificar claves.

Las claves se definen cuando se crean almacenes de objetos. Aquí hay dos ejemplos, uno que usa una ruta clave y otro un generador..

thisDb.createObjectStore ("test", keyPath: "email"); thisDb.createObjectStore ("test2", autoIncrement: true);

Podemos modificar nuestra demostración anterior creando un almacén de objetos con una clave de autoincremento:

thisDB.createObjectStore ("people", autoIncrement: true);

Finalmente, podemos tomar la llamada Agregar que usamos antes y eliminar la clave codificada:

var request = store.add (person);

¡Eso es! Ahora puedes agregar datos todo el día. Puedes encontrar esta versión en test7.html.


Lectura de datos

Ahora pasemos a la lectura de datos individuales (veremos más adelante la lectura de conjuntos de datos más grandes). Una vez más, esto se hará en una transacción y será asíncrono. Aquí hay un ejemplo simple:

var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("prueba"); // x es algún valor var ob = objectStore.get (x); ob.onsuccess = function (e) 

Tenga en cuenta que la transacción es de sólo lectura. La llamada a la API es simplemente una llamada a obtener con la clave pasada. Como punto de partida, si piensa que el uso de IndexedDB es un poco detallado, tenga en cuenta que también puede encadenar muchas de esas llamadas. Aquí está exactamente el mismo código escrito mucho más estricto:

db.transaction (["test"], "readonly"). objectStore ("test"). get (X) .onsuccess = function (e) 

En lo personal, todavía encuentro que IndexedDB es un poco complejo, por lo que prefiero el enfoque "desglosado" para ayudarme a hacer un seguimiento de lo que está pasando.

El resultado del controlador de éxito de get es el objeto que almacenó anteriormente. Una vez que tengas ese objeto puedes hacer lo que quieras. En nuestra próxima demo (test8.html) hemos agregado un campo de formulario simple para permitirle ingresar una clave e imprimir el resultado. Aquí hay un ejemplo:


El controlador para el botón Obtener datos se encuentra a continuación:

función getPerson (e) var key = document.querySelector ("# key"). value; if (clave === "" || isNaN (clave)) devolver; var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("personas"); var request = store.get (Number (key)); request.onsuccess = function (e) var result = e.target.result; console.dir (resultado); if (resultado) var s = "

Tecla "+ tecla +"

"; para (campo var en el resultado) s + = campo +" = "+ resultado [campo] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="

Sin coincidencia

";

En su mayor parte, esto debe ser auto explicativo. Obtenga el valor del campo y ejecute una llamada get en el almacén de objetos obtenido de una transacción. Tenga en cuenta que el código de pantalla simplemente obtiene todos Los campos y los vuelca. En una aplicación real, usted (con suerte) sabría lo que contienen sus datos y trabajará con campos específicos.


Leer más datos

Así es como obtendrías un dato. Qué tal un mucho ¿de datos? IndexedDB tiene soporte para lo que se llama un cursor. Un cursor le permite iterar sobre los datos. Puede crear cursores con un rango opcional (un filtro básico) y una dirección.

Como ejemplo, el siguiente bloque de código abre un cursor para recuperar todos los datos de un almacén de objetos. Como todo lo demás que hemos hecho con datos, esto es asíncrono y en una transacción..

var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("prueba"); var cursor = objectStore.openCursor (); cursor.onsuccess = function (e) var res = e.target.result; if (res) console.log ("Key", res.key); console.dir ("Data", res.value); res.continue (); 

Al controlador de éxito se le pasa un objeto de resultado (la variable res arriba). Contiene la clave, el objeto para los datos (en la clave de valor anterior) y un método de continuación que se utiliza para recorrer la siguiente pieza de datos..

En la siguiente función, hemos utilizado un cursor para iterar sobre todos los datos del almacén de objetos. Como estamos trabajando con datos de "persona", hemos llamado a esto GetPeople:

función getPeople (e) var s = ""; db.transaction (["people"], "readonly"). objectStore ("people"). openCursor (). onsuccess = function (e) var cursor = e.target.result; si (cursor) s + = "

Tecla "+ cursor.key +"

"; para (campo var en cursor.value) s + = campo +" = "+ cursor.value [campo] +"
"; s + ="

"; cursor.continue (); document.querySelector (" # status2 "). innerHTML = s;

Puedes ver una demostración completa de esto en tu descarga como archivo. test9.html. Tiene una lógica de Agregar persona como en los ejemplos anteriores, así que simplemente cree algunas personas y luego presione el botón para mostrar todos los datos.


Así que ahora ya sabe cómo obtener una parte de los datos y cómo obtener todos los datos. Vayamos a nuestro último tema: trabajar con índices..


Ellos llaman a este IndexedDB, Derecho?

Hemos estado hablando de IndexedDB para el artículo completo, pero aún no hemos hecho ningún índice de "bueno". Los índices son una parte crucial de los almacenes de objetos IndexedDB. Proporcionan una forma de obtener datos en función de su valor y también especifican si un valor debe ser único dentro de una tienda. Más adelante demostraremos cómo usar índices para obtener un rango de datos..

Primero, ¿cómo creas un índice? Como todo lo demás estructural, deben realizarse en un evento de actualización, básicamente al mismo tiempo que crea su almacén de objetos. Aquí hay un ejemplo:

var objectStore = thisDb.createObjectStore ("people", autoIncrement: true); // primer arg es el nombre del índice, segundo es la ruta (col); objectStore.createIndex ("nombre", "nombre", único: falso); objectStore.createIndex ("correo electrónico", "correo electrónico", unique: true);

En la primera línea creamos la tienda. Tomamos ese resultado (un objeto objectStore) y ejecutamos el createIndex método. El primer argumento es el nombre del índice y el segundo es la propiedad que se indexará. En la mayoría de los casos creo que usarás el mismo nombre para ambos. El argumento final es un conjunto de opciones. Por ahora, solo estamos usando uno, único. El primer índice para el nombre no es único. El segundo para email es. Cuando almacenamos datos, IndexedDB verificará estos índices y se asegurará de que la propiedad del correo electrónico sea única. También hará un poco de manejo de datos en el back-end para asegurar que podamos obtener datos de estos índices..

¿Cómo funciona? Una vez que obtiene un almacén de objetos a través de una transacción, puede solicitar un índice de esa tienda. Usando el código anterior, aquí hay un ejemplo de eso:

var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("personas"); var index = store.index ("nombre"); // nombre es algún valor var solicitud = índice.get (nombre);

Primero obtenemos la transacción, seguido de la tienda y luego el índice. Como hemos dicho antes, puedes encadenar esas primeras tres líneas para que sea un poco más compacto si quieres.

Una vez que tenga un índice, puede realizar una obtener llamar para recuperar datos por nombre. Podríamos hacer algo similar para el correo electrónico también. El resultado de esa llamada es otro objeto asíncrono al que puede enlazar un controlador de éxito de sesión. Aquí hay un ejemplo de ese controlador encontrado en el archivo. test10.html:

request.onsuccess = function (e) var result = e.target.result; if (resultado) var s = "

Nombre "+ nombre +"

"; para (campo var en el resultado) s + = campo +" = "+ resultado [campo] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="

Sin coincidencia

";

Tenga en cuenta que un índice obtener llamada puede devolver múltiples objetos. Ya que nuestro nombre no es único, probablemente deberíamos modificar el código para manejar eso, pero no es obligatorio.

Ahora vamos a patear una muesca. Ha visto el uso de la API de obtención en el índice para obtener un valor basado en esa propiedad. ¿Qué sucede si desea obtener un conjunto de datos más amplio? El último término que vamos a aprender hoy es Rangos. Los rangos son una forma de seleccionar un subconjunto de un índice. Por ejemplo, dado un índice en una propiedad de nombre, podemos usar un rango para encontrar nombres que comiencen con A hasta nombres que comiencen con C. Los rangos vienen en diferentes variedades. Pueden ser "todo lo que esté debajo de un marcador", "todo lo que esté arriba de un marcador" y "algo entre un marcador más bajo y un marcador más alto". Finalmente, solo para hacer las cosas interesantes, los rangos pueden ser inclusivos o exclusivos. Básicamente, eso significa que para un rango que va desde A-C, podemos especificar si queremos incluir A y C en el rango o solo los valores entre ellos. Finalmente, también puedes solicitar rangos ascendentes y descendentes..

Los rangos se crean utilizando un objeto de nivel superior llamado IDBKeyRange. Tiene tres métodos de interés: límite inferior, UpperBound, y Unido. límite inferior se utiliza para crear un rango que comienza en un valor más bajo y devuelve todos los datos "arriba".. UpperBound es lo opuesto. Y finalmente - Unido se utiliza para admitir un conjunto de datos con un límite inferior y superior. Veamos algunos ejemplos:

// Valores sobre 39 var oldRange = IDBKeyRange.lowerBound (39); // Valores 40a dn sobre var oldRange2 = IDBKeyRange.lowerBound (40, true); // 39 y menor ... var youngRange = IDBKeyRange.upperBound (40); // 39 y menor… var youngRange2 = IDBKeyRange.upperBound (39, true); // no es joven ni viejo ... también puede especificar var / Rang = IDBKeyRange.bound inclusiva / exclusiva (20,40)

Una vez que tenga un rango, puede pasarlo al método openCursor de un índice. Esto le da un iterador para recorrer los valores que coinciden con ese rango. De manera práctica, esto no es realmente una búsqueda por sí misma. Puede usar esto para buscar contenido basado en el principio de una cadena, pero no en el medio o al final. Veamos un ejemplo completo. Primero crearemos un formulario simple para buscar personas:

Empezando con: 
Terminando con

Vamos a permitir búsquedas que consistan en cualquiera de los tres tipos de rangos (de nuevo, un valor y más alto, un valor más alto o los valores dentro de dos entradas). Ahora veamos el controlador de eventos para este formulario.

función getPeople (e) var name = document.querySelector ("# nameSearch"). value; var endname = document.querySelector ("# nameSearchEnd"). value; if (name == "" && endname == "") devuelve; var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("personas"); var index = store.index ("nombre"); // Hacer el rango dependiendo de qué tipo estamos haciendo var range; if (name! = "" && endname! = "") range = IDBKeyRange.bound (name, endname);  else if (nombre == "") rango = IDBKeyRange.upperBound (endname);  else range = IDBKeyRange.lowerBound (name);  var s = ""; index.openCursor (range) .onsuccess = function (e) var cursor = e.target.result; si (cursor) s + = "

Tecla "+ cursor.key +"

"; para (campo var en cursor.value) s + = campo +" = "+ cursor.value [campo] +"
"; s + ="

"; cursor.continue (); document.querySelector (" # status "). innerHTML = s;

De arriba a abajo, comenzamos por agarrar los dos campos de formulario. A continuación creamos una transacción y de ahí obtenemos la tienda y el índice. Ahora para la parte semi-compleja. Dado que tenemos tres tipos diferentes de rangos que debemos admitir, tenemos que hacer un poco de lógica condicional para averiguar cuál necesitaremos. El rango que creamos se basa en los campos que rellena. Lo bueno es que una vez que tenemos el rango, simplemente lo pasamos al índice y abrimos el cursor. ¡Eso es! Puedes encontrar este ejemplo completo en test11.html. Asegúrese de ingresar primero algunos valores para que tenga datos para buscar.


Que sigue?

Lo creas o no, solo hemos comenzado nuestra discusión en IndexedDB. En el siguiente artículo, cubriremos temas adicionales, que incluyen actualizaciones y eliminaciones, valores basados ​​en matrices y algunos consejos generales para trabajar con IndexedDB..