Skip to content

HTML5 Storage

29 enero 2012

Hasta hace relativamente poco tiempo, la única forma que tenían los desarrolladores web para almacenar fragmentos de información en el lado cliente era a través de las Cookies. El tipo de almacenamiento de las Cookies es muy primitivo y muy limitado ya que hay que tener en cuenta que cada Cookie viaja adjunta a cada petición que realiza el cliente, de forma que va hacia el servidor y vuelve al cliente en cada Request, lo que genera un mayor tráfico y por tanto nos limita la cantidad de información que podemos enviar.

Otro inconveniente asociado al uso de Cookies era el hecho de que el usuario estuviera realizando múltiples transacciones en diversas ventanas del navegador. Por ejemplo, un usuario podría estar comprando dos billetes de avión diferente cada uno en una ventana distinta del navegador. Si el sitio utiliza Cookies para almacenar la información del usuario cuando el usuario comprara uno de los billetes, se podría encontrar con que realmente se están enviando cookies con información de compra de dos billetes, lo que supondría que el usuario ha comprado dos billetes sin darse cuenta.

Una de las cuestiones que se planteó durante el desarrollo del estándar HTML5 era: ¿No habrá una forma más sencilla de almacenar cierta información en el navegador del cliente sin que tenga que viajar en cada petición y evitar que la información de diversas ventanas  del navegador se mezcle?

Un poco de información y teoría

HTML5 pone a disposición de los desarrolladores una API que permite almacenar una cantidad de información mucho mayor en los navegadores de los usuarios. Esta API define un interfaz Storage y proporciona una implementación concreta de dicho interfaz a través de dos objetos diferentes: localStorage y sessionStorage.

Cada objeto Storage proporciona acceso a una lista de pares clave,valor que serán los que contendrán la información que hemos almacenado. Estos elementos de la lista se conocen como items. Las claves de los items son String incluyendo la cadena vacía que también es una clave válida.

La diferencia fundamental entre el objeto localStorage y sessionStorage es el tiempo que la información permanece disponible. De este modo, en el objeto localStorage, los datos almacenados están disponibles para el navegador en todo momento aunque cerremos todas las ventanas, lo que significa que si queremos eliminar esta información debemos hacerlo explícitamente; por otro lado, en el objeto sessionStorage la información permanece disponible para el navegador hasta que cerremos la ventana, después se elimina.

Este tipo de almacenamiento de información en el navegador proporciona varias ventajas, entre las que destacan:

  1. Las diferentes ventanas abiertas del mismo site comparten estos objetos, lo que nos permite sincronizar información entre diferentes ventanas del navegador en tiempo real, sin necesidad de recargar.
  2. Los datos almacenados no viajan en las peticiones del cliente, lo cual permite almacenar mayor cantidad de información
  3. Podemos almacenar todo tipo de información, no sólo información textual: Podemos almacenar Strings, Numbers, Arrays… (Aunque posteriormente debemos convertirla al objeto en sí, ya que realmente se almacena como String)
  4. La información está disponible incluso si el usuario no tiene conexión en ese momento, lo que nos permite implementar aplicaciones web que trabajen offline. Característica muy útil para aplicaciones móviles.
  5. Cada site que visitemos tiene sus propios objetos Storage, la información sólo se comparte entre ventanas bajo el mismo dominio.

Definición del Interfaz Storage

interface Storage {
  readonly attribute unsigned long length;
  DOMString? key(unsigned long index);
  getter DOMString getItem(DOMString key);
  setter creator void setItem(DOMString key, DOMString value);
  deleter void removeItem(DOMString key);
  void clear();
};

Como vemos, tenemos disponibles una serie de métodos y atributos para controlar estos objetos y acceder a la información que contienen. Los nombres son autodescriptivos y creo que no es necesario explicar su función, no? ;). Mencionar que el método clear() eliminará todos los pares clave, valor que tuviéramos almacenados para el dominio actual.

La implementación concreta de los objetos (o atributos como los denomina el W3C) localStorage y sessionStorage se centra en implementar este interfaz e imponer la restricción de ámbito para cada uno de ellos.

Captura de Eventos

Como hemos mencionado previamente, una gran ventaja de disponer de este modo de almacenamiento es que las diversas ventanas (pestañas) que tengamos abiertas para un mismo dominio (por ejemplo dos páginas pertenecientes a rekkeb.wordpress.com) puedan compartir la información contenida en los objetos Storage. Es aquí donde entra en juego el sistema de eventos. Cada vez que se realice un cambio sobre el valor de una clave, se lanzará automáticamente un evento que indicará este cambio y dará información relativa sobre quién lo ha provocado, el tipo de evento, las claves actualizadas… De este modo, cualquier ventana que esté haciendo uso de la información de Storage, podrá conocer que alguien ha realizado un cambio en los valores y saber exactamente qué cambio se ha realizado para actualizarse si fuera necesario.

La definición del interfaz de Eventos es la siguiente:

interface StorageEvent : Event {
  readonly attribute DOMString key;
  readonly attribute DOMString? oldValue;
  readonly attribute DOMString? newValue;
  readonly attribute DOMString url;
  readonly attribute Storage? storageArea;
};

De este modo simplemente tendremos que capturar los eventos de tipo ‘storage’ para conocer cuándo varían los pares clave,valor y tener acceso a toda esta información.

Para identificar el tipo de evento que se acaba de disparar, debemos llevar a cabo una serie de comparaciones:

  1. Cambio de valor con setItem(): El evento tendrá en su atributo key la clave afectada, en el atributo oldValue el antiguo valor que tenía esa clave o null si la clave se acaba de crear y en newValue tendrá el nuevo valor que se le ha asignado.
  2. Borrado de una clave removeItem(): El evento tendrá en su atributo key la clave afectada, en el atributo oldValue el antiguo valor que tenía esa clave  y en newValue tendrá null.
  3. Borrado de todas las claves clear(): Tanto key como oldValue, como newValue serán null.

Ejemplo práctico

Venga, ya lo has conseguido, me has aburrido un montón, olvídate de tanta teoría y muéstrame un ejemplo donde se pueda ver en funcionamiento todo este mecanismo. Pues vamos a ello.

Para acceder a los objetos Storage, necesitamos hacer uso de Javascript.

Para estos ejemplos voy a utilizar el objeto localStorage:

  • Añadir una nueva clave será tan sencillo como: localStorage.setItem(‘rekkeb’,10); O utilizando el método abreviado: localStorage.rekkeb = 10;
  • Recuperar el valor de una clave localStorage.getItem(‘rekkeb’). Si devuelve null indica que la clave no existe.
  • Eliminar una clave: localStorage.removeItem(‘rekkeb’);
  • Limpiar todos los items que tengamos bajo el dominio: localStorage.clear();

Por ejemplo, veamos un trozo de código en Javascript que incrementará el valor de la clave ‘rekkeb’. Para ello, en primer lugar creamos una función que lleve a cabo estas operaciones y luego debemos asignar esta función al evento onclick de un botón en nuestra página:

function incremento(){
   if (localStorage.getItem('rekkeb')){//Comprobamos si existe la clave
     localStorage.setItem('rekkeb', parseInt(localStorage.getItem('rekkeb')) +1);
   }else{//Si no existe la inicializamos
     localStorage.setItem('rekkeb',1);
 }

Con esta simple función cada vez que presionemos el botón de ‘Incrementar‘, sumaremos uno al valor que tenga actualmente la clave ‘rekkeb’. Cada vez que se produzca este incremento, se lanzará un evento que cualquier otra página dentro del mismo dominio podrá capturar. Esto significa que este evento es ignorado en la página actual.

Asi es que, ¿cómo podemos hacer para capturar el evento desde otra página?. Es simple: Debemos asignar el evento ‘storage’ al objeto window de Javascript. Veamos el código completo de una página HTML nueva. En esta ocasión utilizo jQuery en lugar de usar simplemente Javascript.

<!doctype html>
<html>
 <head>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
    <script type="text/javascript">
       $(document).ready(function(){
          window.addEventListener('storage', captura_de_eventos_storage, false);
       });

       function captura_de_eventos_storage(e){
          if (e.key == 'rekkeb'){
             $('#cambios_tr').text(
                $('#cambios_tr').text()+' | '+e.oldValue + ' --> ' + e.newValue
             );
          }
       }
    </script>
 </head>
 <body>
 <header>Valores de la clave: rekkeb</header>
     <section id="mainB">
        <article id="cambios_tr"></article>
     </section>
     <footer>Pie de Pagina</footer>
 </body>
</html>

Este código es muy sencillo y carece de utilidad, pero nos permite mostrar cómo capturar los eventos que se hayan lanzando al manipular las claves de algún objeto Storage y cómo acceder al objeto Event y sus atributos. Para probar este ejemplo necesitaremos dos páginas HTML diferentes. En la primera añadiremos el código Javascript de la función incremento() y se lo asignamos al evento que nos interese del elemento que escojamos y en la segunda página añadimos el código HTML completo que tenéis sobre estas líneas. Abrimos ambas páginas en diferentes pestañas de nuestro navegador (debe soportar HTML5) y veréis como cada vez que llaméis a la función incremento(), se actualiza automáticamente el ‘article‘ #cambios_tr de la segunda página HTML.

Modo visual para ver todos los pares clave,valor

Si queréis tener acceso a todos los pares clave,valor almacenados y modificar sus valores de una forma más visual, podéis hacer uso de las herramientas de desarrollo que existen para cada navegador. En mi caso utilizo Safari y si abrimos el panel de Herramientas de Desarrollo —> Almacenamiento Local —> Archivos Locales, veremos todas las claves definidas actualmente. Os encontraréis una ventana parecida a esta:

Os animo a que practiquéis con esta nueva característica de HTML5 y pongáis en práctica todo lo que aprendáis. Y ya sabéis, cualquier duda, consulta, mejora, aclaración, correción,… será siempre bien recibida 🙂

Más info:

Web Storage | W3C

Anuncios
No comments yet

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: