Safari的html5 localStorage错误:"QUOTA_EXCEEDED_ERR:DOM例外22:尝试向超出配额的存储添加内容."

lei*_*lin 132 javascript html5 web-applications local-storage

我的webapp在ios safari私密浏览中有javascript错误:

JavaScript的:错误

未定义

QUOTA_EXCEEDED_ERR:DOM例外22:尝试向存储添加内容......

我的代码:

localStorage.setItem('test',1)
Run Code Online (Sandbox Code Playgroud)

Kin*_*rog 183

显然这是设计的.当Safari(OS X或iOS)处于隐私浏览模式时,它看起来好像localStorage可用,但尝试调用setItem会抛出异常.

store.js line 73
"QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota."
Run Code Online (Sandbox Code Playgroud)

发生的事情是窗口对象仍然localStorage在全局命名空间中公开,但是当您调用时setItem,抛出此异常.任何调用都会removeItem被忽略.

我相信最简单的修复(虽然我还没有测试过这个交叉浏览器)是改变功能isLocalStorageNameSupported()来测试你也可以设置一些值.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 查看[this gist](https://gist.github.com/paulirish/5558557),其中显示了Paul Irish检测本地存储的简要历史. (5认同)
  • 类似于Paul Irish的例子,我建议在win && win [localStorageName]中更改`return localStorageName ;;在`返回true`.然后你有一个安全返回true或false的函数,具体取决于localStorage的可用性.例如:`if(isLocalStorageNameSupported()){/*你可以使用localStorage.setItem*/} else {/*你不能使用localStorage.setItem*/} (5认同)
  • 因此,如果localStorage无法在Safari中运行,那么将所有内容存储在Cookie中是下一个最佳选择吗? (4认同)

cyb*_*bat 38

上面链接上发布的修复程序对我不起作用.这样做:

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

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

  • 您(和@KingKongFrog)使用window.sessionStorage检测您是否可以写入localStorage或者我们是否处于奇怪的复制 - 粘贴拼写错误循环中的任何特殊原因? (20认同)
  • @Novocaine我的评论指出他们在一个存在的函数中使用sessionStorage来检查localStorage支持.是的,它可能仍然有效,但是,正如所写的那样,函数名称会误导实际测试的内容.我选择评论,而不是编辑,因为我以为我错过了一些东西,并希望向这些家伙学习.不幸的是,他们没有回复或做出更正,所以我们在这里. (7认同)
  • @Yetti编辑过. (3认同)
  • @Yetti感谢您的澄清.我现在看到你在做什么.; - ] (3认同)
  • @Dawson没有,因为我调用了函数`isLocalStorageNameSupported`并且正在检查`window.sessionStorage`.相同的最终结果,但有点混乱.编辑答案以澄清. (2认同)

phi*_*reo 25

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

一种解决方案是在每个使用实例中执行try/catch或Modernizr检查setItem.

但是,如果你想要一个简单地全局停止抛出此错误的垫片,为了防止其他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.');
    }
}
Run Code Online (Sandbox Code Playgroud)


Pie*_*oux 11

在我的上下文中,刚开发了一个类抽象.当我的应用程序启动时,我通过调用getStorage()检查localStorage是否正在工作.此功能还返回:

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

在我的代码中,我从不直接调用localStorage.我调用cusSto global var,我通过调用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();
Run Code Online (Sandbox Code Playgroud)

  • 谢谢皮埃尔,你的回答激励了我.我最终把它打包在一个名为[memorystorage]的漂亮模块中(https://download.github.io/memorystorage).当然是开源的.对于有相同问题的其他人,请查看它可能会对您有所帮助. (2认同)
  • @ user1149244*这不应该存储在浏览器中的值吗?*不,它不能.客户端从一个页面刷新到另一个页面刷新有三种方法:cookies,sessionStorage/localStorage和IndexedDB.最后两个相对较新.sessionStorage和localStorage得到广泛支持,因此您可以在任何地方使用它.**除了隐私浏览模式**,这就是这个问题.程序破了,因为存储不存在.memorystorage只提供在页面上始终有效的回退,但它实际上无法保存数据.这是一个存根.但没有错误. (2认同)

kar*_*com 5

似乎Safari 11改变了行为,现在本地存储可在专用浏览器窗口中工作。万岁!

我们曾经在Safari私人浏览中失败的Web应用程序现在可以完美运行。在Chrome的专用浏览模式下,它始终可以正常运行,该模式始终允许写入本地存储。

Apple的Safari技术预览版发行说明 -和WebKit发行说明 -于2017年5月发布的第29版中对此进行了记录。

特别:

  • 修复了在私人浏览模式或WebDriver会话中保存到localStorage时出现QuotaExceededError- r215315