error localStorage de html5 con Safari :" QUOTA EXCEEDED ERR: DOM Excepción 22: Se intentó agregar algo al almacenamiento que excedía la cuota."


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

JavaScript: error

Indefinido

QUOTA_EXCEEDED_ERR:DOM Excepción 22:Se intentó agregar algo al almacenamiento...

Mi código:

localStorage.setItem('test',1)
Author: Rubens Mariuzzo, 2013-01-28

12 answers

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 lanza 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 window todavía expone localStorage en el espacio de nombres global, pero cuando se llama a setItem, se lanza esta excepción. Cualquier llamada a removeItem es ignorada.

Creo que la solución más simple (aunque aún 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;
    }
}
 180
Author: KingKongFrog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-26 10:44:40

La corrección publicada en el enlace anterior no funcionó para mí. Esto hizo:

function isLocalStorageNameSupported() {
  var testKey = 'test', storage = window.localStorage;
  try {
    storage.setItem(testKey, '1');
    storage.removeItem(testKey);
    return true;
  } catch (error) {
    return false;
  }
}

Derivado de http://m.cg/post/13095478393/detect-private-browsing-mode-in-mobile-safari-on-ios5

 36
Author: cyberwombat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-20 18:30:41

Como se mencionó en otras respuestas, siempre obtendrá el error QuotaExceededError en el modo Safari Private Browser tanto en iOS como en OS X cuando se llame a localStorage.setItem (o sessionStorage.setItem).

Una solución es hacer un try/catch o Modernizr check en cada instancia de uso de setItem.

Sin embargo, si desea una cuña que simplemente detenga globalmente este error, para evitar que el resto de su JavaScript se rompa, 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.');
    }
}
 24
Author: philfreo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-22 19:17:30

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

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

En mi código nunca llamo a localStorage directamente. I call cusSto global var, i had initialised by calling 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();
 11
Author: Pierre Le Roux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-08 13:56:01

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 adaptarse a la mayoría de las personas que solo quieren que una aplicación de una sola página siga siendo funcional (a pesar de que no hay persistencia de datos 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 = {};
        };
    }
})();
 4
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-25 09:59:42

Tuve el mismo problema usando el framework Ionic (Angular + Cordova). Sé que esto no resuelve el problema, pero es el código para aplicaciones Angulares basado en las respuestas anteriores. Tendrá 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

Disfrute de su codificación!

 3
Author: jorgecasar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-24 21:37:54

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

Esto resulta en que isLocalStorageAvailable se establece inmediatamente cuando se inyecta el servicio por primera vez y evita ejecutar innecesariamente la comprobación 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');
      }
    };
  }
]);
 2
Author: Pier-Luc Gendreau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-20 16:43:48

Acabo de crear este repositorio para proporcionar características 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 característica 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 a window.localStorage si es compatible o crea un almacenamiento de cookies. Establece StorageService.sessionStorage a window.sessionStorage si es admite o crea un almacenamiento en memoria para SPA, almacenamiento de cookies con funciones de sesión para SPA no.

 1
Author: Ahmet Can Güven,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-14 07:25:46

Parece que Safari 11 cambia el comportamiento, y ahora el almacenamiento local funciona en una ventana privada del navegador. ¡Hurra!

Nuestra aplicación web que solía fallar en la navegación privada de Safari ahora funciona perfectamente. Siempre funcionó bien en el modo de navegación privada de Chrome, que siempre ha permitido escribir en el almacenamiento local.

Esto está documentado en las notas de la versión de Apple Safari Technology Preview - y las notas de la versión de WebKit - para la versión 29, que fue en mayo de 2017.

Específicamente:

  • Se corrigió QuotaExceededError al guardar en localStorage en modo de navegación privada o sesiones de WebDriver - r215315
 1
Author: karlbecker_com,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-01 16:59:49

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

Compartir en Es6 Ejemplo completo de localStorage de lectura y escritura con comprobación 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.

 0
Author: Tarandeep Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-10 18:41:20
var mod = 'test';
      try {
        sessionStorage.setItem(mod, mod);
        sessionStorage.removeItem(mod);
        return true;
      } catch (e) {
        return false;
      }
 0
Author: Naim DOGAN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-04 11:46:53

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://stackoverflow.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 existe localStorage y se puede usar y en el caso negativo, crea un almacenamiento local falso y lo usa en lugar del localStorage original. Por favor, hágamelo saber si necesita más información.

 -2
Author: Bogdan Mates,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-28 20:42:10