Inicialmente los navegadores web solamente mostraban aquella información que el servidor proveía y practicamente más allá del renderizado de la página no hacían mucho más. Desde hace muchos años esto ha evolucionado grandemente y a dado paso a los navegadores que conocemos en la actualidad.
Los navegadores actuales están en un punto, en el cual se pueden tener aplicaciones completamente independientes sin necesidad de una API, solo con cargar nuestro frontend y tener todos los datos de manera estática. Incluso podemos tener sitios web que sin estar conectados a internet funcionen. ¿Pero cómo ocurre esto?
Pues la respuesta a esto es sencilla: los navegadores guardan los datos de las páginas en que navegamos, y la manera en que guardan dicha información, es por medio de los protagonistas de este artículo LocalStorage / SessionStorage / IndexedDB.
A lo largo del artículo iremos viendo cada uno de los métodos de almacenar información en una aplicación web, y cuales y por qué, utilizar en cada momento.
El sessionStorage
es posiblemente (desde mi experiencia) el menos utilizado de los métodos para almacenar información en una aplicación web. Este método básicamente te permite de manera dinámica almacenar información de la forma llave-valor pero solo en la pestaña en la que el usuario se encuentra actualmente, lo que implica que si esta pestaña es cerrada, los datos se pierden.
Ventajas
Desventajas
A continuación un pequeño ejemplo de cómo utilizar el sessionStorage:
// set a value
sessionStorage.setItem('input', sessionValue.value);
// get a value
sessionStorage.getItem('input');
// remove a single item
sessionStorage.removeItem('input');
// clear the whole sessionStorage
sessionStorage.clear();
El localStorage es muy similar al sessionStorage, con la única diferencia que este puede ser compartido entre varias ventanas del navegador y perdura en el tiempo.
Ventajas
Desventajas
Las operaciones del localStorage son similares a las antes vistas:
// set a value
localStorage.setItem('input', sessionValue.value);
// get a value
localStorage.getItem('input');
// remove a single item
localStorage.removeItem('input');
// clear the whole localStorage
localStorage.clear();
El caso del indexedDB es completamente diferente a los métodos anteriores, dado que cómo su nombre lo indica, es una base de datos. Dicha base de datos es almacenada de manera local en el navegador y permite hacer consultas y demás operaciones disponibles en una base de datos común.
Las diferencias más considerables y el por qué de utilizar IndexedDB sobre localStorage, está dado por las opciones de búsqueda y filtrado que proporciona esta funcionalidad similares a una base de datos, que para el manejo de un cúmulo grande de datos mejoran grandemente el rendimiento de la aplicación. Puesto que el localstorage solo almacena valores de la manera llave-valor, y si se quisiera almacenar un listado, habría que serializarlo dentro del navegador y para cada consulta obtener todos estos datos en memoria y hacer las operaciones pertinentes, mientras que con indexedDB, todas estas operaciones serían manejadas por el navegador y solo se obtendría el resultado de las consultas.
Ventajas
Desventajas
Promises
Ejemplo de indexedDB
// open the indexedDB connection
const request = window.indexedDB.open("MyTestDatabase", 1);
// instance of the current DB
let db;
// The first time that the current version of the DB is
// created the next method is called and this is used
// usually for create the tables the first time or update
// the tables if is a new version and it is necessary
request.onupgradeneeded = (event) => {
const db = event.target.result;
const objectStore = db.createObjectStore("data", {keyPath: "key"});
objectStore.createIndex("value", "value");
};
// The basic operations en the DB, should be executed after the
// next event is called
request.onsuccess = (event) => {
db = event.target.result;
const dataTransaction = db.transaction(['data'], 'readwrite');
dataTransaction.objectStore('data').get('input').onsuccess = (event) => {
indexDBValue.value = (event.target.result && event.target.result.value) || '';
};
};
Como se puede ver en el ejemplo anterior, el solo configurar la base de datos más simple que se pueda tener, lleva toda esta serie de acciones, y todavía no se han realizado acciones sobre la DB. A continuación un ejemplo sencillo basado en el código anterior de cómo obtener, guardar y eliminar información.
function saveIndexDBStorage() {
const transaction = db.transaction(['data'], 'readwrite');
// get the instance of the table
const objectStore = transaction.objectStore('data');
// check if the value exist in the table
const request = objectStore.get('input');
request.onsuccess = () => {
if (request.result) {
// if the value exist, update it
const data = request.result;
data.value = indexDBValue.value;
objectStore.put(data);
} else {
// if the value doesn't exist, create it
objectStore.add({key: 'input', value: indexDBValue.value});
}
};
}
function clearIndexDBStorage() {
const transaction = db.transaction(['data'], 'readwrite');
// get the instance of the table
const objectStore = transaction.objectStore('data');
// remove the value in the table
objectStore.delete('input');
}
Un ejemplo del uso de indexedDB puede ser visto en devdocs.io/offline. En este sitio se pueden encontrar una gran cantidad de documentación de tecnologías y el mismo cuenta con la funcionalidad de descargarse offline la información. Básicamente lo que se hace, es descargar toda la documentación para una DB local y luego, sin tener internet se puede consumir toda esta información a la cual se pueden hacer búsquedas, filtrados y las mismas operaciones que cuando se estaba online. Este tipo de ventajas son las que se ganan al usar indexedDB, pero no siempre es la mejor opción y usualmente es más que suficiente lo que brinda el localstorage.
Espero el artículo te haya sido de agrado y no duden dejar en los comentarios sus opiniones.
Si deseas ver los códigos de ejemplo utilizados en el artículo, puedes obtenerlos en este proyecto que de manera muy simple, tiene un ejemplo de cada una de las tres maneras de almacenar información en el navegador.
Happy coding!