HTML5 trae un montón de nuevas posibilidades al navegador. Se ha hablado mucho del formato de vídeo, del canvas, los websockets, de los nuevos controles de formulario pero a mí en particular me ha interesado especialmente aquello de una BD en el cliente. Es un tema que no está tan documentado como el resto y que en muchos libros de HTML5 o ni se menciona o se hace de pasada. Y lo que es peor, hay información en blogs pero a nada que esté desfasada los ejemplos no funcionan como la llamada a setVersion(). Así que mucho ojo, si lees sobre este tema, procura que sea información reciente.

Pues parece que va en serio. Había un par de modelos en liza, uno basado en SQLite llamado WebSQL y otro más del estilo noSQL. Aunque WebSQL éstá soportado aún por Safari, Opera y Chrome el consorcio ha dicho que WebSQL no va a formar parte del estándar, por tanto el w3 se decanta por el otro modelo, llamado IndexedDB y que viene a ser un estilo CouchDB, MongoDB, etc... es decir, olvídate de SQL, da la bienvenida a los ObjectStores, Bases de datos que se lo ponen a huevo a las aplicaciones javascript.

Contenidos de indexedDB en la consola de desarrollador de chrome
Conexión y estilo

No voy a poner todo el código aquí pero sí la parte de la conexión que es lo más curioso junto con las consultas, que son algo durillas si estás acostumbrado al SQL. Esto es Javascript y en el caso de los métodos en torno a IndexedDB funcionan de forma asíncrona. Es decir, al dar la orden de abrir la BD el programa no se detiene para hacerlo, sino que deja una petición que debe ser recogida por un handler (onsuccess, onerror, etc...). Con las operaciones CRUD es lo mismo. Y por otro lado hay operaciones como la de crear el ObjectStore que solo se pueden llevar a cabo dentro de onupgradeneeded de lo contrario te salta una excepción de illegal state. Cosas así que francamente me han traido de cabeza y con la conclusión de que IndexedDB necesita un wrapper para todos los navegadores que nos haga la vida más fácil, que seguramente ya lo habrá.

Otra cosa curiosa con la que he jugado es con el cambio de versiones. Podemos pasarle un parámetro numérico a la llamada open para indicarla la versión de la BD. IndexedDB mantiene internamente un control de versiones por lo visto. Si cambiamos a una versión nueva se disparará el evento onupgradeneeded donde podremos ajustar la BD. Ese evento también se dispará la primera vez que se abre la BD y ahí es donde se deben crear tablas e índices.

var db;
			var openedDB;
			var database = "linksdb";
			var description = "A database containing interesting links";
			var objectStore = 'links';
		    var openDB;
		/**
		 * openCreate
		 * opens and/or creates an IndexedDB database
		 */
		function openCreate () {
			// We could open changing version ..open(database,3)
			var openDB = indexedDB.open(database);

			// This is how we pass the DB instance to our var
			openDB.onsuccess = function(event) {
				db = event.target.result;
				console.log('Database opened ' + db);
			};

			// Very importante event fired when
			// 1. ObjectStore first time creation
			// 2. Version change
			openDB.onupgradeneeded  = function (event) {
				// value of previous db instance is lost!! we get it back
				// using the event
				db = this.result;
				console.log("updgrade needed: " + db);
				 try {
				 	//db.deleteObjectStore(objectStore);
				 	console.log("Object store deleted");

					var store = db.createObjectStore(objectStore,{keyPath: 'id', autoIncrement:true});
				 	console.log("Object store created");

					store.createIndex("link", "link", { unique: false });
					console.log("Index created on link");
					store.createIndex("description", "description", { unique: false });
					console.log("Index created on description");

				} catch  (e) {
					console.log("Exception creating object store: " + e);
				}
			}

			openDB.onerror = function(event) {
				console.log('Something went wrong...');
			};

		}
Demo CRUD
Logs del ejemplo de indexedDB en chrome

Bueno, basta de cháchara. Aquí debajo he metido todo el código de una BD indexedDB, que he comprobado y programado con la ayuda de Chrome (es donde me ha funcionado sin problema no he probado a actualizar el firefox y de explorer ya jejeje pa qué). Importante:

  • Abre la consola de desarrollador la parte Console para los logs y Resource para ver la BD
  • Pincha en el enlace de OPEN/CREATE, y prueba las operaciones
El código fuente está glosado con referencias y algunas anotaciones que iba tomando, como por ejemplo dónde se mete la BBDD en el sistema de ficheros, alternativas, etc... Esta demo lo que hace es gestionar una tabla llamada links en las que metemos pues eso, enlaces de páginas con una descripción. Se le configura un id autonumérico (ver código) y también metemos índices a los campos link y description para que luego nos permita hacer búsquedas con esos campos.

IndexedDB CRUD, tested successfully with win32 Chrome v28.0.1500.95 m

OPEN/CREATE Database
IndexedDB CRUD
CREATE
url description Create data

READ one
id READ one record
READ ALL
Link Search by link

UPDATE
id url description Update data

DELETE
id delete data
delete all
Drop Database