Cuando el navegador bloquea el almacenamiento local
Leer una preferencia guardada puede lanzar una excepción, devolver algo de una versión anterior de la aplicación o volver vacío sin aviso. Tres casos que rompen la pantalla entera si el acceso no está encapsulado.
Guardar una preferencia en el navegador parece la operación más inofensiva que existe. En una pestaña de incógnito, con cookies de terceros bloqueadas, con el disco lleno o con la configuración del navegador endurecida, esa misma línea lanza una excepción.
Y si está en el camino de inicialización, la excepción no rompe la preferencia: rompe la pantalla.
Las tres formas de fallar
| Situación | Qué pasa | Qué se ve si no está contemplado |
|---|---|---|
| Almacenamiento deshabilitado o sin cuota | El acceso lanza excepción | La aplicación no arranca |
| Valor de una versión anterior | Se lee algo con otra forma | Errores al usar campos que ya no existen |
| Valor corrupto o editado a mano | El parseo falla o devuelve cualquier cosa | Estado inconsistente difícil de reproducir |
El segundo es el más subestimado. El almacenamiento del navegador es persistente de verdad: lo que guardó una versión de hace dos años sigue ahí, y lo va a leer el código de hoy.
Encapsular el acceso
El comentario de review que resuelve la familia entera es el mismo: el acceso directo no va repartido por la aplicación, va detrás de una capa chica.
Qué hace esa capa
- Captura. Toda lectura y escritura, en un
try. Si falla, la aplicación sigue con el valor por defecto en memoria. - Valida la forma. Lo leído se verifica contra un esquema antes de usarse; lo que no cumple se descarta como si no estuviera.
- Tolera lo viejo. Descartar entradas inválidas y conservar las válidas, en vez de tirar todo o confiar en todo.
- Centraliza las claves. Una constante por clave, para que no haya dos formas de escribir el mismo nombre —el bug silencioso de siempre—.
Qué conviene guardar ahí y qué no
La otra mitad del comentario es sobre el contenido. El almacenamiento del navegador es visible y editable por el usuario, no viaja entre dispositivos y puede desaparecer en cualquier momento.
Antes de seguir, predecí
La regla es la misma que con la validación: conveniencia sí, verdad no. Y hay una consideración de privacidad: datos personales guardados en el dispositivo son datos que sobreviven al cierre de sesión, salvo que alguien se ocupe de limpiarlos.
Cuando cambia la forma de lo guardado
Si la estructura cambia entre versiones, hace falta una decisión explícita, porque los dos extremos son malos: confiar en lo viejo rompe, y borrar todo hace que el usuario pierda sus preferencias sin motivo.
Lo que funciona
- Versionar lo guardado, con un número dentro del valor o en el nombre de la clave.
- Migrar lo que se pueda al leer, una sola vez, y descartar lo que no.
- Tratar lo desconocido como ausente. Es lo que convierte un error en un valor por defecto.
Más a fondo · nivel seniorEsto mismo vale para cualquier estado que sobrevive al despliegue
El patrón excede al navegador: es el mismo problema de un archivo de configuración escrito por una versión anterior, de un mensaje en una cola con el formato viejo o de una fila en la base guardada por el código del año pasado. Todo dato que persiste más que el código que lo escribió necesita versión, validación al leer y una política explícita para lo que no se entiende.
Una línea que puede tirar la pantalla
Hay 3 problemas en este cambio. Tocá la línea donde creas que está.
| 1 | 1 | ||
| 2 | 2 | ||
| 3 | |||
| 4 | |||
| 3 | 5 | ||
| 4 | |||
| 6 | |||
BloqueaLa lectura corre durante la inicialización, así que la excepción tira la pantalla En una pestaña de incógnito, con datos de sitio bloqueados o con el navegador endurecido, acceder a localStorage lanza. Y como está en el valor inicial del estado, la excepción sube durante el renderizado y se lleva puesto todo el componente. La preferencia era opcional; el resultado es una pantalla en blanco. | |||
| 7 | |||
| 8 | |||
| 9 | |||
BloqueaLa escritura también puede lanzar, y por otro motivo Además de los casos de la lectura, escribir puede fallar por cuota agotada, que es un modo de falla distinto y aparece con el uso, no al principio. Cada acceso —lectura y escritura— necesita su propio try/catch, y el catch tiene que dejar la aplicación andando sin la preferencia. | |||
| 10 | |||
| 5 | 11 | ||
| 6 | 12 | ||
| 7 | 13 | ||
Dos accesos al almacenamiento, tres formas de fallar, y la aplicación andaba perfecto en la máquina de quien lo escribió.
La regla general de la frontera
Cierre
Autoevaluación
¿Lo entendiste?
Práctica
PreguntaQué hay que poder responder antes de escribir esto
Dos preguntas: ¿la aplicación funciona sin esta preferencia? y ¿qué pasa si lo guardado tiene una forma vieja? La primera decide si va en un try/catch o si es un error de verdad. La segunda aparece el día que cambie el formato de lo guardado, y ahí lo leído es una cadena que ya no se parece a lo que el código espera.