ChatGPT解决这个技术问题 Extra ChatGPT

QuotaExceededError: Dom 异常 22: 尝试向存储中添加超出配额的内容

在带有 iOS 7 的 iPhone 上使用 LocalStorage 会引发此错误。我一直在寻找解决方案,但考虑到我什至没有私下浏览,没有什么是相关的。

我不明白为什么在 iOS 7 中默认会禁用 localStorage,但似乎是这样?我也在其他网站上测试过,但没有运气。我什至尝试使用以下网站对其进行测试:http://arty.name/localstorage.html,但出于某种奇怪的原因,它似乎根本没有保存任何东西。

有没有人遇到过同样的问题,只是他们有运气解决它?我应该切换我的存储方式吗?

我尝试通过仅存储几行信息来对其进行硬调试,但无济于事。我使用标准的 localStorage.setItem() 函数来保存。

这通常意味着您试图存储超出可用存储空间大小的东西。您使用的是什么浏览器(Safari、Chrome 等)?您能否再分享一些您一直在使用的代码以及您尝试存储的数据(如果可能)。
这应该被视为 Safari 端的错误或问题。不能在隐身模式下使用 localStorage 是没有意义的......
使用 a feature detect that tests for this specific issue。如果存储不可用,请考虑使用 memoryStorage 填充 localStorage。 免责声明:我是链接包的作者
2017 年 4 月,一个补丁被合并到 Safari 中,因此它与其他浏览器保持一致。可能会登陆 Safari 11。bugs.webkit.org/show_bug.cgi?id=157010
我可以确认这已在 Safari iOS 11 中得到修复。在 iPhone6 和 iPhone8 上成功测试了隐私浏览 + sessionStorage.setItem() 然后 sessionStorage.getItem()。

s
sandstrom

当 Safari 处于隐私模式浏览时,可能会发生这种情况。在隐私浏览中,本地存储根本不可用。

一种解决方案是警告用户应用程序需要非私有模式才能工作。

更新:这已在 Safari 11 中修复,因此该行为现在与其他浏览器保持一致。


今天(不到 24 小时后),你的帖子对我来说非常有帮助和及时。作为参考,以下是打开/关闭隐私浏览的方法:imore.com/how-use-private-browsing-ios-7-safari
+1 解决了我的问题。在尝试加载和保存信息但收到此错误之前,我正在检查 LocalStorage (if( typeof Storage != 'undefined' ) { ... }) 是否存在。结果发现 Storage 即使在它不可用时仍然被定义。从现在开始每当我使用 LocalStorage 时都使用 try/catch。
谢谢!野生动物园的奇怪错误。应该提供更多信息。 :D
从 Safari 技术预览版 29 开始,可能会有一个修复:“在隐私浏览模式或 WebDriver 会话中保存到 localStorage 时修复了 QuotaExceededError”。请参阅developer.apple.com/safari/technology-preview/release-notes
如果 storage limit is reached 可以通过保存图像轻松完成,也会发生这种情况。
p
philfreo

正如其他答案中提到的,当调用 localStorage.setItem(或 sessionStorage.setItem)时,您总是会在 iOS 和 OS X 上的 Safari 私人浏览器模式下获得 QuotaExceededError。

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

但是,如果您想要一个简单地全局阻止此错误抛出的 shim,以防止 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.');
    }
}

如果您无论如何都无法使用 setItem,为什么还要将它添加到 Storage 对象中?
如果您希望您的应用程序在 Safari 私有模式下不被完全破坏,我的代码片段的要点是简单地忽略抛出 JS 错误。
D
DrewT

我使用这个返回 truefalse 的简单函数来测试 localStorage 的可用性:

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

现在您可以在使用之前测试 localStorage.setItem() 的可用性。例子:

if ( isLocalStorageNameSupported() ) {
    // can use localStorage.setItem('item','value')
} else {
    // can't use localStorage.setItem('item','value')
}

我错过了什么吗?为什么在名为 isLocalStorageNameSupported 的方法中使用 window.sessionStorage 而不是 window.localStorage
@lthar - 请参阅此处的文档:w3schools.com/html/html5_webstorage.asp 最重要的是这部分:HTML local storage provides two objects for storing data on the client: window.localStorage - stores data with no expiration date window.sessionStorage - stores data for one session (data is lost when the browser tab is closed)
@DrewT,但是如果您删除测试密钥,这种情况有什么区别?如果我要删除它,我将测试密钥存储在哪里并不重要。我错了吗?为什么会话存储比本地存储更好?
@TurakVladyslav 你说得对,这里真的没有什么区别,只是如果你想测试你的开发,使用 sessionStorage 可以更容易地设置断点。对于哪个“更好”没有真正的论据,这实际上只是个人偏好,在谨慎方面会犯错。主要需要注意的是 sessionStoragelocalStorage 都是 HTML5 webstorage API 的实现。
d
defvol

I happened to run with the same issue in iOS 7(有些设备没有模拟器)。

看起来 iOS 7 中的 Safari 具有较低的存储配额,这显然是通过拥有较长的历史日志来达到的。

我想最好的做法是捕捉异常。

Modernizr 项目有一个简单的补丁,您应该尝试类似的方法:https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js


S
Stickley

这是基于上述 DrewT 回答的扩展解决方案,如果 localStorage 不可用,则使用 cookie。它使用 Mozilla 的 docCookies library

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

在您的来源中,只需使用:

localStorageSet( 'foobar', 'yes' );
...
var foo = localStorageGet( 'foobar' );
...

J
Josef Engelfrost

正如其他答案中已经解释的那样,当处于隐私浏览模式时 Safari 将总是在尝试使用 localStorage.setItem() 保存数据时抛出此异常。

为了解决这个问题,我编写了一个模仿 localStorage 的假 localStorage,包括方法和事件。

假本地存储:https://gist.github.com/engelfrost/fd707819658f72b42f55

这可能不是解决问题的一个好的通用解决方案。对于我的场景来说,这是一个很好的解决方案,在这种情况下,替代方案是对已经存在的应用程序进行重大重写。


它究竟修复了什么?它不会持久化任何东西,那有什么意义呢?
它在隐私浏览模式下“修复”了 Safari。 (这在我的回答中不清楚,感谢您指出这一点。我将编辑我的答案)。无论如何,在隐私浏览模式下都不应该保留任何内容,因此不保留在这里不是相关问题。这对我来说解决的是允许用户运行已经存在的应用程序,而无需进行重大重写,即使在 Safari 中处于隐私浏览模式时也是如此。
J
John

更新 (2016-11-01)

我正在使用下面提到的 AmplifyJS 来解决这个问题。但是,对于私人浏览中的 Safari,它正在回退到基于内存的存储。在我的情况下,这是不合适的,因为这意味着存储在刷新时被清除,即使用户仍在隐私浏览中。

另外,我注意到一些用户总是在 iOS Safari 上以隐私模式浏览。出于这个原因,Safari 的一个更好的后备方案是使用 cookie(如果可用)。默认情况下,即使在私密浏览中仍可访问 cookie。当然,退出隐私浏览时会被清除,但刷新时不会被清除。

我找到了 local-storage-fallback 库。从文档中:

目的 对于像“私人浏览”这样的浏览器设置,即使在较新的浏览器中,依赖工作的 window.localStorage 也已成为一个问题。即使它可能存在,它也会在尝试使用 setItem 或 getItem 时抛出异常。该模块将运行适当的检查以查看可能可用的浏览器存储机制,然后将其公开。它使用与 localStorage 相同的 API,因此在大多数情况下它应该可以作为替代品。

当心陷阱:

CookieStorage 有存储限制。这里要小心。 MemoryStorage 不会在页面加载之间持续存在。这或多或少是防止页面崩溃的权宜之计,但对于不进行整页加载的网站来说可能就足够了。

TL;博士:

使用 local-storage-fallback(具有 .getItem(prop).setItem(prop, val) 的统一 API):

检查并使用适合浏览器的存储适配器(localStorage、sessionStorage、cookies、内存)

原始答案

要添加以前的答案,一种可能的解决方法是更改存储方法。有一些库(例如 AmplifyJSPersistJS)可以提供帮助。这两个库都允许通过多个后端进行持久的客户端存储。

对于 AmplifyJS

localStorage IE 8+ Firefox 3.5+ Safari 4+ Chrome Opera 10.5+ iPhone 2+ Android 2+ sessionStorage IE 8+ Firefox 2+ Safari 4+ Chrome Opera 10.5+ iPhone 2+ Android 2+ globalStorage Firefox 2+ userData IE 5 - 7 userData在较新版本的 IE 中也存在,但由于 IE 9 实现中的怪癖,如果支持 localStorage,我们不会注册 userData。内存 如果没有其他存储类型可用,则提供内存存储作为后备。

对于 PersistentJS

flash:Flash 8 持久存储。 gears:基于 Google Gears 的持久存储。 localstorage:HTML5 草稿存储。 globalstorage:HTML5 草稿存储(旧规范)。即:Internet Explorer 用户数据行为。 cookie:基于 cookie 的持久存储。

它们提供了一个抽象层,因此您不必担心选择存储类型。请记住,根据存储类型,可能会有一些限制(例如大小限制)。现在,我正在使用 AmplifyJS,但我仍然需要在 iOS 7/Safari/etc 上进行更多测试。看看它是否真的解决了问题。


编辑约翰:我知道你和 Jonathan Alzetta 可能是同一个帐户,你只是想改进你的答案,但如果是这样,你真的应该以 Jonathan Alzetta 的身份登录并编辑这个答案,然后它就不会通过审查队列。如果需要,请恢复您的帐户。
s
sandstrom

2017 年 4 月,一个补丁被合并到 Safari 中,因此它与其他浏览器保持一致。这是随 Safari 11 一起发布的。

https://bugs.webkit.org/show_bug.cgi?id=157010


c
clayostrom

这个问题和答案帮助我解决了在 Parse 中注册新用户的特定问题。

因为 signUp( attrs, options ) 函数使用本地存储来保持会话,如果用户处于隐私浏览模式,它会抛出“QuotaExceededError: DOM Exception 22: 尝试向存储中添加超出配额的内容”。异常和成功/错误函数永远不会被调用。

就我而言,由于从未调用过错误函数,因此最初似乎是在提交时触发点击事件或在注册成功时定义的重定向的问题。

包括对用户的警告解决了该问题。

解析 Javascript SDK 参考 https://parse.com/docs/js/api/classes/Parse.User.html#methods_signUp

使用用户名(或电子邮件)和密码注册新用户。这将在服务器上创建一个新的 Parse.User,并将会话保存在 localStorage 中,以便您可以使用 {@link #current} 访问用户。