La API IndexedDB te proporciona un rápido almacenamientos clave/valor en tu navegador. Es soportado por más navegadores de los que te piensas (gracias a shim, puede funcionar incluso en los más antiguos). Esto significa que cuando surja la necesidad, tendrás una manera de almacenar una colección de datos en el navegador del usuario, sin tener que depender de la conexión a Internet. Lo malo de todo esto es que la API de IndexedDB es muy engorrosa y muy difícil de utilizar. Lo bueno es que existe una pequeña librería que te puede ser de gran ayuda. Su nombre es db.js y en este tutorial te mostraremos cómo utilizarla.
Cómo utilizar db.js
IndexedDB se basa principalmente en la creación de callbacks, detección de errores, y trabaja con una gran cantidad de variables temporales. Db.js te hace esto más sencillo y te muestra una interfaz más lineal, con la que es fácil trabajar para cualquier fan de jQuery. La librería incluso utiliza el mismo mecanismo deferred/promise al igual que jQuery. Si no sabes de lo que estoy hablando, no te preocupes, lo verás mucho más claro una vez que veas algo de código.
Para este propósito, vamos a desarrollar una pequeña aplicación de demostración. Vamos a hacer lo siguiente:
- En primer lugar, definiremos el esquema de un nuevo almacenamiento clave/valor, junto con un número de versión
- Intentaremos abrir la base de datos, y si todo ha ido bien procederemos
- Estableceremos un detector del evento clic en el elemento "Add". En el cuerpo del listener, aprovecharemos para insertar un registro en la base de datos y mostrar el elemento en la página
- Por último, cuando un elemento sea clicado, eliminaremos el registro adecuado de la base de datos y lo quitaremos de la página.
Además de ser súper rápidas, estas operaciones también son persistentes, de modo que, si actualizas la página o cierras el navegador, los datos seguirán ahí.
El código
El primer paso es definir el esquema de nuestro almacén de datos. A diferencia de las bases de datos relacionales como MySQL, no tenemos la noción de tablas con columnas y tipos predefinidos. IndexedDB puede tener objetos JavaScript arbitrarios dentro de un solo almacén de datos. El único requisito en este paso es elegir un campo id y si quieres que tenga incremento automático.
db.open({ name: 'database', version: 2, schema: { items: { key: { keyPath: 'id', autoIncrement: true }, indexes: { color: { unique: false } } } } })
La definición de un índice le dirá a IndexedDB que debe buscar esa característica en los objetos insertados en el almacén de datos. A continuación, recuperará y ordenará todos los objetos que contienen este índice. En el ejemplo anterior estoy definiendo un índice sobre la propiedad de un color y diciéndole a db.js que no quiero que sea único (si lo fuese, solo sería capaz de almacenar un objeto de ese color). No uso este índice directamente en la aplicación, pero decidí incluirlo de todos modos para mostrarte cómo se hace. Si deseas actualizar el esquema, tendrás que incrementar el número de versión también.
Al igual que con todo lo demás, la apertura de una base de datos en IndexedDB es asíncrona y puede fallar en muchos casos (el navegador no lo soporta, el número de versión es incorrecto, o si, por ejemplo, el usuario navega en modo de incógnito). Tenemos que pasar un callback al método done() después de abrir la base de datos, para asegurarnos de que todo ha salido bien. También es necesario obtener una referencia del objeto del servidor, que más tarde necesitaremos para ejecutar consultas.
db.open({ name: 'database', version: 2, schema: { items: { key: { keyPath: 'id', autoIncrement: true }, indexes: { color: { unique: false } } } } }).done(function(server){ // The database was successfully opened. We can // run transactions using the server varaible // Listen for the document ready event, as we will // be working with the dom $(function() { // Cache some selectors var add = $('#add'), items = $('#items'); var colors = ['blue', 'green', 'yellow', 'pink']; // On dom.ready, select all items and update the #items ul server.items.query().filter().execute().done(function(results){ if(!results){ return; } $.each(results, function(){ createItem(this); }); }); // Listen for clicks on the add button add.click(function(){ var item = { text: (new Date()).toTimeString(), color: colors[ Math.floor( Math.random()*colors.length )] }; server.items.add(item).done(function(){ createItem(item); }); // If you wish to update an item: // server.items.update({id:123, color:'pink', text:'asdf'}); }); // When an item is clicked, remove it from the database. $('#items').on('click', 'li:not(#add)', function(){ var item = $(this); server.items.remove( item.data('id') ).done(function(){ item.fadeOut(); }); }); function createItem(item){ var tmp = $('
'); tmp.addClass( item.color ) .data('id', item.id) .find('p').text( item.text ); items.prepend(tmp); } }); }).fail(function(error){ console.error("An error occured: ", error); });
Fuente: tutorialzine.com