localstorage create javascript html5 web-applications local-storage

javascript - create - Error html5 localStorage con Safari: "QUOTA_EXCEEDED_ERR: DOM Exception 22: se intentó agregar algo al almacenamiento que excedió la cuota".



save localstorage javascript (10)

Mi aplicación web tiene errores de javascript en la navegación privada de ios safari:

JavaScript: error

indefinido

QUOTA_EXCEEDED_ERR: DOM Exception 22: se intentó agregar algo al almacenamiento ...

mi código:

localStorage.setItem(''test'',1)


No lo use si no es compatible y para verificar el soporte solo llame a esta función

compartiendo en Es6 full read and write localStorage Ejemplo con cheque de soporte

const LOCAL_STORAGE_KEY = ''tds_app_localdata''; const isSupported = () => { try { localStorage.setItem(''supported'', ''1''); localStorage.removeItem(''supported''); return true; } catch (error) { return false; } }; const writeToLocalStorage = components => (isSupported ? localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(components)) : components); const isEmpty = component => (!component || Object.keys(component).length === 0); const readFromLocalStorage = () => (isSupported ? JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) || {} : null);

Esto asegurará que sus claves estén configuradas y recuperadas correctamente en todos los navegadores.


Acabo de crear este repo para proporcionar las funciones sessionStorage y localStorage para navegadores no compatibles o deshabilitados.

Navegadores compatibles

  • IE5 +
  • Chrome todas las versiones
  • Mozilla todas las versiones
  • Yandex todas las versiones

Cómo funciona

Detecta la función con el tipo de almacenamiento.

function(type) { var testKey = ''__isSupported'', storage = window[type]; try { storage.setItem(testKey, ''1''); storage.removeItem(testKey); return true; } catch (error) { return false; } };

Establece StorageService.localStorage en window.localStorage si es compatible o crea un almacenamiento de cookies. Establece StorageService.sessionStorage en window.sessionStorage si es compatible o crea un almacenamiento en memoria para SPA, almacenamiento de cookies con características de sesion para no SPA.


Aparentemente esto es por diseño. Cuando Safari (OS X o iOS) está en modo de navegación privada, parece que localStorage está disponible, pero intentar llamar a setItem arroja una excepción.

store.js line 73 "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota."

Lo que sucede es que el objeto ventana todavía expone localStorage en el espacio de nombres global, pero cuando llama a setItem , se lanza esta excepción. Cualquier llamada a removeItem se ignora.

Creo que la solución más simple (aunque todavía no he probado este navegador cruzado) sería alterar la función isLocalStorageNameSupported() para probar que también puede establecer algún valor.

https://github.com/marcuswestin/store.js/issues/42

function isLocalStorageNameSupported() { var testKey = ''test'', storage = window.sessionStorage; try { storage.setItem(testKey, ''1''); storage.removeItem(testKey); return localStorageName in win && win[localStorageName]; } catch (error) { return false; } }


Aquí hay una solución para AngularJS usando un IIFE y aprovechando el hecho de que los servicios son únicos .

Esto hace que isLocalStorageAvailable se establezca inmediatamente cuando el servicio se inyecta por primera vez y evita ejecutar innecesariamente el cheque cada vez que se necesita acceder al almacenamiento local.

angular.module(''app.auth.services'', []).service(''Session'', [''$log'', ''$window'', function Session($log, $window) { var isLocalStorageAvailable = (function() { try { $window.localStorage.world = ''hello''; delete $window.localStorage.world; return true; } catch (ex) { return false; } })(); this.store = function(key, value) { if (isLocalStorageAvailable) { $window.localStorage[key] = value; } else { $log.warn(''Local Storage is not available''); } }; } ]);


Como se menciona en otras respuestas, siempre obtendrá el QuotaExceededError en el modo de navegador privado Safari en iOS y OS X cuando se localStorage.setItem (o sessionStorage.setItem ).

Una solución es hacer una comprobación setItem / catch o Modernizr en cada instancia de uso de setItem .

Sin embargo, si quiere un complemento que simplemente detenga 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.''); } }


El siguiente script resolvió mi problema:

// Fake localStorage implementation. // Mimics localStorage, including events. // It will work just like localStorage, except for the persistant storage part. var fakeLocalStorage = function() { var fakeLocalStorage = {}; var storage; // If Storage exists we modify it to write to our fakeLocalStorage object instead. // If Storage does not exist we create an empty object. if (window.Storage && window.localStorage) { storage = window.Storage.prototype; } else { // We don''t bother implementing a fake Storage object window.localStorage = {}; storage = window.localStorage; } // For older IE if (!window.location.origin) { window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? '':'' + window.location.port: ''''); } var dispatchStorageEvent = function(key, newValue) { var oldValue = (key == null) ? null : storage.getItem(key); // `==` to match both null and undefined var url = location.href.substr(location.origin.length); var storageEvent = document.createEvent(''StorageEvent''); // For IE, http://.com/a/25514935/1214183 storageEvent.initStorageEvent(''storage'', false, false, key, oldValue, newValue, url, null); window.dispatchEvent(storageEvent); }; storage.key = function(i) { var key = Object.keys(fakeLocalStorage)[i]; return typeof key === ''string'' ? key : null; }; storage.getItem = function(key) { return typeof fakeLocalStorage[key] === ''string'' ? fakeLocalStorage[key] : null; }; storage.setItem = function(key, value) { dispatchStorageEvent(key, value); fakeLocalStorage[key] = String(value); }; storage.removeItem = function(key) { dispatchStorageEvent(key, null); delete fakeLocalStorage[key]; }; storage.clear = function() { dispatchStorageEvent(null, null); fakeLocalStorage = {}; }; }; // Example of how to use it if (typeof window.localStorage === ''object'') { // Safari will throw a fit if we try to use localStorage.setItem in private browsing mode. try { localStorage.setItem(''localStorageTest'', 1); localStorage.removeItem(''localStorageTest''); } catch (e) { fakeLocalStorage(); } } else { // Use fake localStorage for any browser that does not support it. fakeLocalStorage(); }

Comprueba si localStorage existe y se puede usar y, en el caso negativo, crea un almacenamiento local falso y lo usa en lugar del localStorage original. Por favor, avíseme si necesita más información.


En mi contexto, acaba de desarrollar una abstracción de clase. Cuando se inicia mi aplicación, compruebo si localStorage funciona llamando a getStorage () . Esta función también devuelve:

  • localStorage si localStorage está funcionando
  • o una implementación de una clase personalizada LocalStorageAlternative

En mi código, nunca llamo localStorage directamente. Llamo a cusSto var global, lo había inicializado llamando a getStorage () .

De esta manera, funciona con navegación privada o versiones específicas de Safari

function getStorage() { var storageImpl; try { localStorage.setItem("storage", ""); localStorage.removeItem("storage"); storageImpl = localStorage; } catch (err) { storageImpl = new LocalStorageAlternative(); } return storageImpl; } function LocalStorageAlternative() { var structureLocalStorage = {}; this.setItem = function (key, value) { structureLocalStorage[key] = value; } this.getItem = function (key) { if(typeof structureLocalStorage[key] != ''undefined'' ) { return structureLocalStorage[key]; } else { return null; } } this.removeItem = function (key) { structureLocalStorage[key] = undefined; } } cusSto = getStorage();



Para ampliar las respuestas de los demás, aquí hay una solución compacta que no expone / agrega ninguna variable nueva. No cubre todas las bases, pero debería adecuarse a la mayoría de las personas que solo desean que una aplicación de una sola página permanezca funcional (a pesar de que no hay datos persistentes después de la recarga).

(function(){ try { localStorage.setItem(''_storage_test'', ''test''); localStorage.removeItem(''_storage_test''); } catch (exc){ var tmp_storage = {}; var p = ''__unique__''; // Prefix all keys to avoid matching built-ins Storage.prototype.setItem = function(k, v){ tmp_storage[p + k] = v; }; Storage.prototype.getItem = function(k){ return tmp_storage[p + k] === undefined ? null : tmp_storage[p + k]; }; Storage.prototype.removeItem = function(k){ delete tmp_storage[p + k]; }; Storage.prototype.clear = function(){ tmp_storage = {}; }; } })();


Tuve el mismo problema al usar el marco iónico (Angular + Córdova). Sé que esto no resuelve el problema, pero es el código de las aplicaciones angulares basado en las respuestas anteriores. Tendrás una solución efímera para localStorage en la versión iOS de Safari.

Aquí está el código:

angular.module(''myApp.factories'', []) .factory(''$fakeStorage'', [ function(){ function FakeStorage() {}; FakeStorage.prototype.setItem = function (key, value) { this[key] = value; }; FakeStorage.prototype.getItem = function (key) { return typeof this[key] == ''undefined'' ? null : this[key]; } FakeStorage.prototype.removeItem = function (key) { this[key] = undefined; }; FakeStorage.prototype.clear = function(){ for (var key in this) { if( this.hasOwnProperty(key) ) { this.removeItem(key); } } }; FakeStorage.prototype.key = function(index){ return Object.keys(this)[index]; }; return new FakeStorage(); } ]) .factory(''$localstorage'', [ ''$window'', ''$fakeStorage'', function($window, $fakeStorage) { function isStorageSupported(storageName) { var testKey = ''test'', storage = $window[storageName]; try { storage.setItem(testKey, ''1''); storage.removeItem(testKey); return true; } catch (error) { return false; } } var storage = isStorageSupported(''localStorage'') ? $window.localStorage : $fakeStorage; return { set: function(key, value) { storage.setItem(key, value); }, get: function(key, defaultValue) { return storage.getItem(key) || defaultValue; }, setObject: function(key, value) { storage.setItem(key, JSON.stringify(value)); }, getObject: function(key) { return JSON.parse(storage.getItem(key) || ''{}''); }, remove: function(key){ storage.removeItem(key); }, clear: function() { storage.clear(); }, key: function(index){ storage.key(index); } } } ]);

Fuente: https://gist.github.com/jorgecasar/61fda6590dc2bb17e871

¡Disfruta de tu codificación!