javascript - localstorage - QuotaExceededError: excepción de Dom 22: se intentó agregar algo al almacenamiento que excedía la cuota
localstorage react (9)
Actualización (2016-11-01)
Estaba utilizando AmplifyJS que se menciona a continuación para solucionar este problema. Sin embargo, para Safari en la navegación privada, estaba retrocediendo a un almacenamiento basado en memoria. En mi caso, no fue apropiado porque significa que el almacenamiento se borra en la actualización, incluso si el usuario todavía se encuentra en la navegación privada.
Además, he notado que varios usuarios siempre están navegando en modo privado en iOS Safari. Por esa razón, una mejor alternativa para Safari es usar cookies (si están disponibles). Por defecto, las cookies siguen siendo accesibles incluso en la navegación privada. Por supuesto, se borran al salir de la navegación privada, pero no se borran al actualizar.
Encontré la librería local-storage-fallback . De la documentación:
Propósito
Con configuraciones de navegador como "Navegación privada" se ha convertido en un problema depender de una ventana de trabajo. Almacenamiento local, incluso en navegadores más nuevos. Aunque pueda existir, lanzará excepciones cuando intente usar setItem o getItem. Este módulo ejecutará las comprobaciones adecuadas para ver qué mecanismo de almacenamiento del navegador podría estar disponible y luego lo expondrá. Utiliza la misma API que localStorage, por lo que debería funcionar como un reemplazo directo en la mayoría de los casos.
Cuidado con las trampas:
- CookieStorage tiene límites de almacenamiento. Ten cuidado aqui
- MemoryStorage no persistirá entre las cargas de la página. Esto es más o menos una brecha para evitar bloqueos de página, pero puede ser suficiente para sitios web que no cargan la página completa.
TL; DR:
Use local-storage-fallback .getItem(prop)
API unificada con .getItem(prop)
y .setItem(prop, val)
):
Verifique y use el adaptador de almacenamiento apropiado para el navegador (almacenamiento local, almacenamiento de sesión, cookies, memoria)
Respuesta original
Para agregar respuestas anteriores, una posible solución sería cambiar el método de almacenamiento. Hay algunas AmplifyJS como AmplifyJS y PersistJS que pueden ayudar. Ambas bibliotecas permiten el almacenamiento persistente del lado del cliente a través de varios backends.
Para amplificar js
almacenamiento local
- IE 8+
- Firefox 3.5+
- Safari 4+
- Cromo
- Opera 10.5+
- iPhone 2+
- Android 2+
sessionStorage
- IE 8+
- Firefox 2+
- Safari 4+
- Cromo
- Opera 10.5+
- iPhone 2+
- Android 2+
almacenamiento global
- Firefox 2+
datos del usuario
- IE 5 - 7
- userData también existe en las versiones más recientes de IE, pero debido a las peculiaridades de la implementación de IE 9, no registramos userData si se admite localStorage.
memoria
- Un almacén en memoria se proporciona como respaldo si ninguno de los otros tipos de almacenamiento está disponible.
Para PersistentJS
- flash: flash 8 almacenamiento persistente.
- gears: almacenamiento persistente basado en Google Gears.
- localstorage: almacenamiento de borrador HTML5.
- globalstorage: almacenamiento de borradores HTML5 (antigua especificación).
- Es decir: comportamientos de datos de usuario de Internet Explorer.
- cookie: almacenamiento persistente basado en cookies.
Ofrecen una capa de abstracción para que no tenga que preocuparse por elegir el tipo de almacenamiento. Tenga en cuenta que puede haber algunas limitaciones (como los límites de tamaño) dependiendo del tipo de almacenamiento. En este momento, estoy usando AmplifyJS, pero todavía tengo que hacer más pruebas en iOS 7 / Safari / etc. Para ver si realmente resuelve el problema.
El uso de LocalStorage en iPhone con iOS 7 produce este error. He estado buscando una solución, pero teniendo en cuenta que ni siquiera estoy navegando en privado, nada es relevante.
No entiendo por qué localStorage estaría deshabilitado de manera predeterminada en iOS 7, pero parece que lo está. He probado en otros sitios web también, pero sin suerte. Incluso intenté probarlo usando este sitio web: http://arty.name/localstorage.html , pero no parece que esté guardando nada en absoluto por alguna extraña razón.
¿Alguien ha tenido el mismo problema, solo han tenido suerte para solucionarlo? ¿Debo cambiar mi método de almacenamiento?
Intenté realizar una depuración difícil almacenando solo unas pocas líneas de información, pero fue en vano. localStorage.setItem()
función localStorage.setItem()
estándar para guardar.
Aquí hay una solución ampliada basada en la respuesta de DrewT anterior que utiliza cookies si localStorage no está disponible. Utiliza la biblioteca docCookies de Mozilla:
function localStorageGet( pKey ) {
if( localStorageSupported() ) {
return localStorage[pKey];
} else {
return docCookies.getItem( ''localstorage.''+pKey );
}
}
function localStorageSet( pKey, pValue ) {
if( localStorageSupported() ) {
localStorage[pKey] = pValue;
} else {
docCookies.setItem( ''localstorage.''+pKey, pValue );
}
}
// global to cache value
var gStorageSupported = undefined;
function localStorageSupported() {
var testKey = ''test'', storage = window.sessionStorage;
if( gStorageSupported === undefined ) {
try {
storage.setItem(testKey, ''1'');
storage.removeItem(testKey);
gStorageSupported = true;
} catch (error) {
gStorageSupported = false;
}
}
return gStorageSupported;
}
En su fuente, solo use:
localStorageSet( ''foobar'', ''yes'' );
...
var foo = localStorageGet( ''foobar'' );
...
Como se mencionó en otras respuestas, siempre obtendrá el QuotaExceededError en el modo de navegador privado de Safari en iOS y OS X cuando se localStorage.setItem
(o sessionStorage.setItem
).
Una solución es hacer una prueba try / catch o Modernizr en cada instancia de usar setItem
.
Sin embargo, si desea un shim que simplemente detiene globalmente este error, para evitar que se rompa el resto de su JavaScript, puede usar esto:
https://gist.github.com/philfreo/68ea3cd980d72383c951
// Safari, in Private Browsing Mode, looks like it supports localStorage but all calls to setItem
// throw QuotaExceededError. We''re going to detect this and just silently drop any calls to setItem
// to avoid the entire page breaking, without having to do a check at each usage of Storage.
if (typeof localStorage === ''object'') {
try {
localStorage.setItem(''localStorage'', 1);
localStorage.removeItem(''localStorage'');
} catch (e) {
Storage.prototype._setItem = Storage.prototype.setItem;
Storage.prototype.setItem = function() {};
alert(''Your web browser does not support storing settings locally. In Safari, the most common cause of this is using "Private Browsing Mode". Some settings may not save or some features may not work properly for you.'');
}
}
Como ya se explicó en otras respuestas, cuando está en modo de navegación privada, Safari siempre lanzará esta excepción cuando intente guardar datos con localStorage.setItem()
.
Para solucionar esto escribí un localStorage falso que imita a localStorage, tanto métodos como eventos.
Almacenamiento local falso: https://gist.github.com/engelfrost/fd707819658f72b42f55
Probablemente esta no sea una buena solución general al problema. Esta fue una buena solución para mi escenario, donde la alternativa sería reescribir en una aplicación ya existente.
En abril de 2017, un parche se fusionó con Safari, por lo que se alineó con los otros navegadores. Esto fue lanzado con Safari 11.
Esta pregunta y respuesta me ayudaron a resolver un problema específico al registrar nuevos usuarios en Parse.
Debido a que la función SignUp (attrs, options) usa el almacenamiento local para persistir la sesión, si un usuario está en modo de navegación privada, lanza el mensaje "QuotaExceededError: DOM Exception 22: se intentó agregar algo al almacenamiento que excedió la cuota". Excepción y las funciones de éxito / error nunca son llamadas.
En mi caso, debido a que la función de error nunca se llama, inicialmente parecía ser un problema con la activación del evento de clic en el envío o la redirección definida en el momento del registro.
Incluyendo una advertencia para los usuarios resuelto el problema.
Parse Javascript SDK Reference https://parse.com/docs/js/api/classes/Parse.User.html#methods_signUp
Registra un nuevo usuario con un nombre de usuario (o correo electrónico) y contraseña. Esto creará un nuevo Parse.User en el servidor y también persistirá la sesión en localStorage para que pueda acceder al usuario usando {@link #current}.
Esto puede ocurrir cuando Safari está en modo privado navegando. Mientras que en la navegación privada, el almacenamiento local no está disponible en absoluto.
Una solución es advertir al usuario que la aplicación necesita un modo no privado para funcionar.
ACTUALIZACIÓN: Esto se ha corregido en bugs.webkit.org/show_bug.cgi?id=157010 , por lo que el comportamiento ahora está alineado con otros navegadores.
Utilizo esta función simple, que devuelve true
o false
, para probar la disponibilidad de localStorage:
isLocalStorageNameSupported = function() {
var testKey = ''test'', storage = window.sessionStorage;
try {
storage.setItem(testKey, ''1'');
storage.removeItem(testKey);
return true;
} catch (error) {
return false;
}
}
Ahora puede probar la disponibilidad de localStorage.setItem()
antes de usarlo. Ejemplo:
if ( isLocalStorageNameSupported() ) {
// can use localStorage.setItem(''item'',''value'')
} else {
// can''t use localStorage.setItem(''item'',''value'')
}
Me encontré con el mismo problema en iOS 7 (con algunos dispositivos sin simuladores).
Parece que Safari en iOS 7 tiene una cuota de almacenamiento más baja, que aparentemente se alcanza al tener un registro de larga historia.
Supongo que la mejor práctica será atrapar la excepción.
El proyecto Modernizr tiene un parche fácil, debe probar algo similar: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js