Local Storage y Session Storage en HTML5
Cuando la web nació hace muchos muchos años de la mano de Tim Bernes Lee, nació como una mera transacción electrónica entre un cliente y un servidor: el cliente solicita un recurso, el servidor ofrece una respuesta. Listo, no hay más magia que esto.
Para el servidor, una petición es indistinta de otra inmediata y el ciclo comienza nuevamente. Es por esto que se dice que el protocolo HTTP no tiene estado, o sea, es stateless. Es nuestra responsabilidad como desarrolladores solventar esta limitación y asegurarnos de mantener el estado entre peticiones.
Para esta tarea, era muy habitual utilizar cookies, estos pequeños pedacitos de información que viajan en cada petición entre el cliente y el servidor, de manera de recordarle “Hey! te acuerdas de mi?”. Entonces, si tenemos el problema resuelto, ¿para qué necesitamos otro método nuevo? Bueno, resulta que las cookies no son tan buena solución:
- Aumentan el peso de cada petición al servidor, ya que toda la información guardada en las cookies debe viajar al servidor y volver.
- Tienen una limitación de 4kb de espacio disponible.
- No todo el mundo tiene las cookies habilitadas, sobre todo luego de que se publicaran como ciertas empresas utilizan las cookies para registrar nuestro comportamiento en la web.
Por suerte, una de las nuevas específicaciones de la W3C y WHATWG, indica como podemos utilizar Javascript para guardar información en los navegadores de nuestros usuarios que expire al finalizar la sesión, o que no expire en lo absoluto a menos que el usuario lo indique.
Entran a la cancha Local Storage y Session Storage
¿Qué son Local Storage y Session Storage?
Puesto de manera sencilla, son dos métodos que nos ofrecen los navegadores para guardar pares de valores llave/valor, de manera sencilla y dándonos de manera standard unos 5 megabytes. Al igual que las cookies, ésta información no desaparece si uno navega fuera de la página.
Al contrario de las cookies, esta información queda guardada en la computadora del cliente y no viaja con cada petición. No hay excusas para no utilizar ninguno de los dos métodos, ya que se encuentran soportados por prácticamente todos los navegadores, excepto IE6, IE7 y Safari 3.2. Comenzar a utilizarlo es muy sencillo:
/* Utilizando la Api de Local Storage, podemos guardar y luego recuperar un valor */ localStorage.setItem('saludo', 'Bienvenidos a localStorage'); valor = localStorage.getItem('saludo'); /* Pero esta no es la única manera, ya que también podemos hacer lo siguiente */ localStorage['saludo'] = 'Este saludo también es válido'; valor = localStorage['saludo']; /* Y claro, esto también es válido */ localStorage.saludo = 'Y este es mi método favorito'; valor = localStorage.saludo;
Pero esto no es lo único que podemos hacer, ya que las APIs de Local Storage como la de Session Storage nos ofrecen un par de métodos más para controlar la información que contienen.
/* Podemos saber cuántos elementos tenemos guardados */ alert('Tenemos ' + localStorage.length + ' elementos dentro de Local Storage'); /* Eliminar elementos también es muy sencillo de lograr */ localStorage.removeItem('saludo'); /* Y si queremos acceder a la información de localStorage de manera secuencial, entonces lo hacemos gracias a su método 'key' que devuelve la clave en determinada posición */ for(var i=0, t=localStorage.length; i < t; i++) { key = localStorage.key(i); alert('Para la clave ' + key + ' el valor es: ' + localStorage[key]); }
Vale aclarar que todo lo mismo vale en este punto, si queremos trabajar con sessionStorage, que guardará los valores durante el tiempo de sesión del navegador y se borrarán cuando el navegador se reinicie. Esto no sucede con localStorage, que conservará los valores aunque cerremos y volvamos a acceder al navegador.
¿Cómo cargar local Storage de manera más inteligente?
Luego de estar trabajando un tiempo con localStorage o sessionStorage, comienza a notarse un patrón cuando queremos asegurarnos de la disponibilidad del Storage. Al comienzo hacemos las siguientes pruebas:
if('localStorage' in window && window['localStorage'] !== null) { alert('Genial, tenemos un navegador decente que soporta LocalStorage'); var storage = localStorage } else { alert('Como seguimos utilizando un navegador viejo, Santa Claus no nos traerá nada esta Navidad'); }
Como puden ver, el utilizar el if para chequear la existencia de localStorage se puede volver un tanto molesto y un “anti-patrón”. ¿Y qué pasa si no tenemos soporte para localStorage? ¿Nuestra aplicación debe fallar? ¿O deberíamos ofrecer una solución que degrade de manera “grácil”?
Aquí es donde surge la necesidad de trabajar con un método que sirva ya en tanto tengamos soporte, o no. Y que no de errores al momento de chequear la disponibilidad de localStorage. Este es el código que estoy utilizando en mis desarrollos:
// Existe localStorage? var storage; try { if (localStorage.getItem) { storage = localStorage; } } catch(e) { storage = {}; }
De esta manera, dentro de la variable storage tendremos o una referencia a localStorage lista para utilizar, o un objeto que no reemplazará la funcionalidad de localStorage, pero al menos no dará error inmediatamente cuando lo utilicemos, para luego implementar alguna librería que de soporte, como Amplify.js.
No Strings Attached
Una de las limitantes más molestas de localStorage y sessionStorage es que, al igual que con las cookies, solo podemos guardar cadenas de texto. Nada de valores nativos como enteros, float, ni siquiera un triste boolean (que sería “false”). Ni hablar de los objetos:
persona = {nombre: 'Pablo Rigazzi', edad: 33}; localStorage.autor = persona; alert(localStorage.autor); // Esto nos devuelve el texto "[object Object]"
Entonces, ¿cómo podemos hacer para superar esta limitante? Afortunadamente, hay una técnica bastante simple para guardar objetos completos dentro de localStorage, para luego recuperarlos y volver a convertirlos y este método es utilizar el objeto JSON, disponible en los mismos navegadores que soportan localStorage. Retomando el ejemplo anterior:
// Primero convertimos el objeto en una cadena de texto localStorage.autor = JSON.stringify(persona); /* Y ahora, al recuperarlo, convertimos el string nuevamente en un objeto */ var autor = JSON.parse(localStorage.autor); alert(typeof autor); // Aqui obtendremos que el tipo de la variable es "object"
Vientos de cambio
Los navegadores nos dan un mecanismo para enterarnos cuando otra página realizó cambios sobre los valores de localStorage (y solo localStorage). Para esto, lanzan un evento llamado “storage” que es muy fácilmente atrapable. Lo malo, no es un evento “cancelable”, esto eso, el navegador solamente nos avisa del cambio, pero no tenemos manera de impedir que ese cambio se realice.
Hay que tener en cuenta que este evento se dispara si el cambio se realizó en otra página (abierta en otra ventana o en otro tab), que esté asociada al mismo localStorage con el que estamos trabajando (o sea, es del mismo dominio).
hay_cambio = function(e) { console.log("Dentro de la clave " + e.key + " el valor anterior era " + e.oldValue + ' y el nuevo es ' + e.newValue); } if(window.addEventListener) { window.addEventListener('storage', hay_cambio, false); } else { // Hay que soportar IE6, 7 y 8, lo lamento window.attachEvent('onstorage', hay_cambio); }
Aquí es donde para probar, podemos abrir otra ventana del mismo dominio donde estemos trabajando, disparar FireBug o la consola de Chrome y tipear: localStorage.clave = "nuevo valor."
y ver como se dispara el evento en el tab o ventana original.
Ejemplos de utilización de Session Storage y Local Storage:
- Guardar resultados temporalmente de una llamada a un webservice.
- Mantener estado de la interfaz de usuario de manera sencilla.
Genial :), si ya estoy haciendo unas pruebas con localStorage
Según lo que tengo entendido, esto del local storage deja cualqueir archivo o información que el sitio crea correspondiente alojada en el computador del cliente…
Qué sucedería si el cliente formateara el pc?
Queda algún respaldo en el server de los datos que le pasamos ó directamente el usuario pierde toda la info?
Martin, lo más lógico es que si un usuario formatea su computadora… TODA la información se pierda no?
La idea de LocalStorage es la de guardar información que no es impresicindible, como datos de login, estado de la interfaz, como cache local para alguna petición AJAX que pueda ser costosa, pero no más. Si antes estabas usando Cookies, esto sería el reemplazo.
Para todo tipo de información más importante del usuario, aquí sigue siendo obligatorio guardarlo del lado del servidor, en una base de datos o donde mejor nos parezca, pero tener esa info en el servidor.
Muy bueno hermano, muchas gracias. Muy bien explicado. Voy a ponerme a probar estos métodos.
Saludos!
Buena la teoría, pero a todo esto me entró una curiosidad:
A que medida, se puede garantizar la seguridad a los datos del localstorage?, es decir si se guarda en el navegador, ya sea en firefox o crhome, donde se pueden modificar estas variables con las herramientas web developers, hay metodos para acceso restringido?, o no es una buena práctica usarlo como “variables de sesiones”?.
Saludos
Jp++
John Paul,
Hay que tener en cuenta, que el Storage dentro del navegador, es como cualquier archivo dentro de la máquina del usuario. Supuestamente es responsabilidad de los navegadores cifrar y proteger estos archivos, pero nada es 100% seguro, como decimos acá en Argentina “a seguro se lo llevaron preso”.
En cuánto a utilizarlo como “variables de Sesión”, yo personalmente lo haría, pero teniendo en cuenta de no utilizar nombres que puedan ser demasiado comunes. Si bien hay un LocalStorage y SessionStorage de 5 megas por CADA dominio que requiera uno, hay que tener en cuenta que cada Javascript que nosotros embebamos ( sean de nuestro dominio o externos ) tienen acceso al localStorage de ESE dominio, pudiendo leer los datos ahi guardados o sobreescribirlos.
Entonces, hay que tener mucho cuidado qué se guarda y bajo que “namespace” (nombre de clave) para evitar colisiones.
excelente post, muchas gracias. Tienes un tutorial que contega todos estos detalles, ya me lei la guía HTML 5.
Saludos,
Pablo y la seguridad se me hace que es mas fácil que alguien coloque contenido malintencionado no?
Pido disculpas por la pregunta ya esta contestada
Avisa!! No me habia enterado. Muy bueno Pablo.
[…] Rigazzi para Maestros del Web.Agrega tu comentario | Enlace permanente al […]
[…] Rigazzi para Maestros del Web.Agrega tu comentario | Enlace permanente al […]