Safari浏览器发生html5 localStorage错误:“QUOTA_EXCEEDED_ERR:DOMexception22:尝试向超出配额的存储添加内容。

我的web应用程序有ios Safari浏览器中的javascript错误:

JavaScript的:错误

未定义

QUOTA_EXCEEDED_ERR:DOMexception22:尝试向存储添加内容…

我的代码:

localStorage.setItem('test',1) 

显然这是devise。 当Safari(OS X或iOS)处于隐私浏览模式时,似乎localStorage可用,但尝试调用setItem会引发exception。

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

会发生什么情况是窗口对象仍在全局名称空间中公开localStorage ,但是当您调用setItem ,会抛出此exception。 任何对removeItem调用都将被忽略。

我相信最简单的修复(虽然我还没有testing过这个跨浏览器)将改变函数isLocalStorageNameSupported()来testing,你也可以设置一些价值。

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; } } 

上面的链接发布修复不适合我。 这样做:

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

派生自http://m.cg/post/13095478393/detect-private-browsing-mode-in-mobile-safari-on-ios5

正如其他答案中所提到的,当调用localStorage.setItem (或sessionStorage.setItem )时,您将始终在iOS和OS X上以Safari私有浏览器模式获取QuotaExceededError。

一个解决scheme是在使用setItem每个实例中执行try / catch或Modernizr检查 。

但是,如果你想要一个简单的全局停止这个错误被抛出,以防止其余的JavaScript中断,你可以使用这个:

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.'); } } 

在我的语境中,只是开发了一个类抽象。 当我的应用程序启动时,我通过调用getStorage()来检查localStorage是否正在工作。 这个函数还返回:

  • 如果localStorage正在工作,则为localStorage
  • 或自定义类LocalStorageAlternative的实现

在我的代码中,我从来没有直接调用localStorage。 我调用cusSto全局variables ,我已经通过调用getStorage()初始化。

这样,它可以与隐私浏览或特定的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(); 

为了扩大他人的答案,这里是一个紧凑的解决scheme,不暴露/添加任何新的variables。 它并不包括所有的基础,但它适合大多数人只是希望单个页面的应用程序保持function(尽pipe重新加载后没有数据持久性)。

 (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 = {}; }; } })(); 

我有使用Ionic框架(Angular + Cordova)相同的问题。 我知道这不能解决问题,但它是基于上述答案的Angular Apps的代码。 您将在IOS版本的Safari上为localStorage提供短暂的解决scheme。

这里是代码:

 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); } } } ]); 

来源: https : //gist.github.com/jorgecasar/61fda6590dc2bb17e871

享受你的编码!

以下是使用IIFE的 AngularJS解决scheme,并利用服务是单例的事实。

这导致isLocalStorageAvailable在服务首次被注入时被立即设置,并且避免每次需要访问本地存储时不必要地运行检查。

 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'); } }; } ]); 

如果不支持,不要使用它,并检查支持只是调用这个function

共享在Es6完全读写本地存储示例与支持检查

 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); 

这将确保您的密钥在所有浏览器上正确设置和检索。

我刚刚创build此回购为不支持或禁用的浏览器提供sessionStoragelocalStoragefunction。

支持的浏览器

  • IE5 +
  • Chrome所有版本
  • Mozilla的所有版本
  • Yandex所有版本

怎么运行的

它使用存储types检测function。

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

StorageService.localStorage设置为window.localStorage如果支持或创buildcookie存储)。 将StorageService.sessionStorage设置为window.sessionStorage如果支持),或者为SPA创build内存存储,具有非SPA的sesionfunction的cookie存储。

以下脚本解决了我的问题:

 // 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(); } 

它检查localStorage是否存在并且可以被使用,在否定的情况下,它会创build一个假的本地存储并使用它而不是原来的localStorage。 请让我知道,如果你需要进一步的信息。