QuotaExceededError:Dom例外22:クォータを超えたものをストレージに追加しようとしました


219

iOS 7を搭載したiPhoneでLocalStorageを使用すると、このエラーがスローされます。私は解決策を探し回っていましたが、私がプライベートでブラウジングすらしていなかったことを考えると、何も関係ありません。

iOS 7でlocalStorageがデフォルトで無効になる理由がわかりませんが、無効になっているようです。他のウェブサイトでもテストしましたが、うまくいきませんでした。私はこのWebサイトhttp://arty.name/localstorage.htmlを使用してテストを試みましたが、奇妙な理由で何も保存していないようです。

誰かが同じ問題を抱えていましたか?彼らだけがそれを修正できたのですか?保存方法を切り替える必要がありますか?

数行の情報を保存するだけでハードデバッグを試みましたが、役に立ちませんでした。localStorage.setItem()保存には標準機能を使用しました。


2
通常は、使用可能なストレージスペースを超えるサイズで何かを保存しようとしたことを意味します。どのブラウザを使用していますか(Safari、Chromeなど)?使用しているコードと、可能であれば格納しようとしているデータをもう少し共有できますか。

3
これは、Safari側のバグまたは問題と見なす必要があります。シークレットモードでlocalStorageを使用できないことは意味がありません...
Maksim Luzik

この特定の問題をテストする機能検出を使用します。ストレージが利用できない場合は、localStorageをmemoryStorageでシミングすることを検討してください免責事項:私はリンクされたパッケージの作成者です
Stijn de Witt 2017

1
2017年4月にパッチがSafariにマージされたため、他のブラウザーと連携しました。おそらくSafari 11に上陸するでしょう。bugs.webkit.org
show_bug.cgi?

2
これはSafari iOS 11で修正されていることを確認できます。プライベートブラウジング+ sessionStorage.setItem()をテストしてから、iPhone6およびiPhone8でsessionStorage.getItem()を正常にテストしました。
Kevin Gaudin

回答:


372

これは、Safariがプライベートモードブラウジングのときに発生する可能性があります。シークレットブラウジング中は、ローカルストレージはまったく利用できません。

1つの解決策は、アプリが機能するために非プライベートモードが必要であることをユーザーに警告することです。

更新:これはSafari 11で修正されたため、動作は他のブラウザーと一致しています。


4
あなたの投稿は、今日(24時間以内)に私にとって非常に役に立ち、タイムリーでした。参考までに、プライベートブラウジングをオン/オフにする方法は次のとおり
Nick

12
+1で問題が解決しました。if( typeof Storage != 'undefined' ) { ... }情報をロードして保存しようとする前にLocalStorage()の存在を確認していましたが、このエラーが発生しました。結局のところStorage、まだそれは使用不可能だ場合でも定義されています。LocalStorageを使用するときは、これからはtry / catchを使用します。
stevendesu 2014

ありがとう!サファリによる奇妙なエラー。もっと有益なはずです。:D
サニーRグプタ

2
Safari Tech Preview 29以降、「プライベートブラウジングモードまたはWebDriverセッションでlocalStorageに保存するときのQuotaExceededErrorが修正されました」という修正が受信される可能性があります。developer.apple.com/safari/technology-preview/release-notesを
Marc Baumbach

1
これは、たとえば画像を保存することで簡単に実行できるストレージ制限に達した場合にも発生する可能性があります。
csalmeida '19年

103

他の回答で述べたように、localStorage.setItem(またはsessionStorage.setItem)が呼び出されると、iOSとOS Xの両方のSafariプライベートブラウザーモードで常にQuotaExceededErrorが発生します。

1つの解決策は、を使用する各インスタンスで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.');
    }
}

1
とにかくそれを使用できないのに、なぜsetItemをStorageオブジェクトに追加するのですか?
ネクロマンサー2016年

4
私のスニペットのポイントは、Safariプライベートモードでアプリが完全に壊れないようにしたい場合に、JSエラーがスローされるのを単に無視することです。
philfreo 2016年

16

trueor を返すこの単純な関数を使用してfalse、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')
}

私は何かを見逃しましたか?と呼ばれるメソッドのwindow.sessionStorage代わりに使用されるのはなぜですか?window.localStorageisLocalStorageNameSupported
Ithar 2016年

@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

@DrewTですが、テストキーを削除した場合のこの状況の違いは何ですか?削除する場合、テストキーをどこに保存してもかまいません。私が間違っている?セッションストレージがローカルストレージよりも優れているのはなぜですか?
Vladyslav Turak

1
@TurakVladyslavそうですねsessionStorage、開発をテストしたい場合に使用すると、ブレークポイントを設定しやすくなることを除いて、ここでは実際に違いはありません。どちらが「より良い」かについての真の議論はなく、注意を怠るのは、ここでの個人的な好みだけです。ノートの主なものは、両方のことであるsessionStoragelocalStorageHTML5のwebstorageのAPIの両方の実装です。
DrewT 2016

5

iOS 7で同じ問題が発生しました(一部のデバイスではシミュレーターがありません)。

iOS 7のSafariの方がストレージクォータが低いようです。これは、履歴ログが長いために達成されているようです。

例外をキャッチすることがベストプラクティスになると思います。

Modernizrプロジェクトには簡単なパッチがあります。https//github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.jsのようなものを試してみてください。


3

これは、localStorageが利用できない場合にCookieを使用する、上記のDrewTの回答に基づく拡張ソリューションです。MozillaのdocCookiesライブラリを使用します

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

2

他の回答ですでに説明したように、プライベートブラウジングモードでは、 Safariはでデータを保存しようとすると、常にこの例外をスローしlocalStorage.setItem()ます。

これを修正するために、メソッドとイベントの両方で、localStorageを模倣する偽のlocalStorageを作成しました。

偽のlocalStorage:https : //gist.github.com/engelfrost/fd707819658f72b42f55

これはおそらく、問題に対する適切な一般的な解決策ではありません。これは私のシナリオにとって良い解決策でした。代替案は、既存のアプリケーションへの大幅な書き換えです。


正確には何を修正しますか?何も持続しないので、何がポイントなのでしょうか?
Esben Skov Pedersen 2017

1
プライベートブラウジングモードでSafariを「修正」します。(これは私の答えでは明確ではありません。指摘してくれてありがとう。私は私の答えを編集します)。プライベートブラウジングモードの場合は何も保持されないため、保持されないことはここでは問題になりません。これで私が修正したのは、Safariのプライベートブラウジングモードでも、ユーザーが既存のアプリケーションを大幅な書き換えなしに実行できるようにすることでした。
Josef Engelfrost 2017年

2

アップデート(2016-11-01)

この問題を回避するには、下記のAmplifyJSを使用していました。ただし、プライベートブラウジングのSafariでは、メモリベースのストレージにフォールバックしていました。私の場合、ユーザーがまだプライベートブラウジングを行っていても、更新時にストレージがクリアされることを意味するため、適切ではありませんでした。

また、iOS Safariで常にプライベートモードでブラウジングしているユーザーが多いことに気づきました。そのため、Safariのより良いフォールバックは、Cookieを使用することです(可能な場合)。デフォルトでは、プライベートブラウジングでもCookieにアクセスできます。もちろん、プライベートブラウジングを終了するとクリアされますが、更新時にクリアされません。

local-storage-fallbackライブラリを見つけました。ドキュメントから:

目的

「プライベートブラウジング」などのブラウザ設定では、新しいブラウザでも、有効なwindow.localStorageに依存することが問題になっています。存在する場合でも、setItemまたはgetItemを使用しようとすると例外がスローされます。このモジュールは、適切なチェックを実行して、使用可能なブラウザーストレージメカニズムを確認し、それを公開します。これはlocalStorageと同じAPIを使用するため、ほとんどの場合、ドロップイン置換として機能するはずです。

落とし穴に注意してください:

  • CookieStorageにはストレージ制限があります。ここで注意してください。
  • MemoryStorageは、ページのロード間で保持されません。これは多かれ少なかれ、ページのクラッシュを防ぐための一時的なギャップですが、ページ全体をロードしないWebサイトには十分な場合があります。

TL; DR:

local-storage-fallbackを使用します(.getItem(prop)およびで統一されたAPI .setItem(prop, val)):

ブラウザに適切なストレージアダプタを確認して使用します(localStorage、sessionStorage、Cookie、メモリ)。

元の答え

以前の回答に加えて、1つの考えられる回避策は、保存方法を変更することです。AmplifyJSPersistJSなどのライブラリがいくつかありますます。どちらのライブラリも、いくつかのバックエンドを介して永続的なクライアント側ストレージを許可します。

AmplifyJSの場合

ローカルストレージ

  • IE 8以降
  • Firefox 3.5以降
  • Safari 4以降
  • クロム
  • Opera 10.5以降
  • iPhone 2+
  • Android 2+

sessionStorage

  • IE 8以降
  • Firefox 2以降
  • Safari 4以降
  • クロム
  • 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などでさらにテストを行う必要があります。それが実際に問題を解決するかどうかを確認します。


編集者のジョン:私はあなたとジョナサンアルゼッタがおそらく同じアカウントであり、あなたは答えを改善しようとしているだけだと思いますが、もしそうなら、本当にジョナサンアルゼッタとしてログインしてこの答えを編集する必要があります。レビューキュー。必要に応じてアカウントを復元します。
DavidS


0

この質問と回答は、Parseでの新規ユーザーの登録に関する特定の問題を解決するのに役立ちました。

signUp(attrs、options)関数はローカルストレージを使用してセッションを永続化するため、ユーザーがプライベートブラウジングモードの場合は、「QuotaExceededError:DOM Exception 22:何かを追加しようとしましたが、クォータを超えました。」例外と成功/エラー関数が呼び出されることはありません。

私の場合、エラー関数は呼び出されないため、送信時にクリックイベントを発生させるか、サインアップの成功時に定義されたリダイレクトで問題が発生したようです。

ユーザーへの警告を含めることで問題は解決しました。

Parse Javascript SDK Reference https://parse.com/docs/js/api/classes/Parse.User.html#methods_signUp

ユーザー名(または電子メール)とパスワードで新しいユーザーをサインアップします。これにより、サーバー上に新しいParse.Userが作成され、{@ link #current}を使用してユーザーにアクセスできるように、localStorageにセッションが永続化されます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.