web-dev-qa-db-ja.com

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

IOS 7を搭載したiPhoneでLocalStorageを使用すると、このエラーが発生します。私はリゾルバントを探していましたが、私が個人的に閲覧することすらしていないことを考えると、何も関係ありません。

なぜlocalStorageがiOS 7でデフォルトで無効にされるのか私は理解していませんが、それはそうですか?私は他のウェブサイトでもテストしましたが、運が悪いです。私はこのウェブサイトを使ってそれをテストしようとさえしました: http://arty.name/localstorage.html 、それはそれが何かを節約しているようには見えませんいくつかの奇妙な理由のために。

誰かが同じ問題を抱えていますか、彼らがそれを直して運が良かっただけですか?保存方法を変更する必要がありますか?

私は数行の情報を格納するだけでそれをハードデバッグしようとしましたが、役に立ちませんでした。私は標準のlocalStorage.setItem()関数を使って保存しました。

216
NicT

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

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

更新:これは Safari 11 で修正されたため、動作は他のブラウザと一致するようになりました。

360
Cristian Dinu

localStorage.setItem(またはsessionStorage.setItem)が呼び出されると、iOSとOS Xの両方で、SafariプライベートブラウザモードでQuotaExceededErrorが常に返されます。

1つの解決策は、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.');
    }
}
103
philfreo

LocalStorageの可用性をテストするために、trueまたはfalseを返すこの単純な関数を使用します。

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')
}
16
DrewT

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

IOS 7のSafariはストレージ割り当て量が少ないように見えますが、これは明らかに長い履歴ログを持つことによって達成されます。

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

Modernizrプロジェクトには簡単なパッチがあります、あなたは似たようなことを試みるべきです: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js

5
defvol

これは、localStorageが利用できない場合にクッキーを使用する上記の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' );
...
3
Stickley

更新(2016-11-01)

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

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

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

目的

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

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

  • CookieStorageには記憶域の制限があります。ここに注意してください。
  • MemoryStorageはページをロードしても持続しません。これは、ページがクラッシュするのを防ぐための多少なりともギャップがありますが、ページ全体を読み込まないWebサイトでは十分な場合があります。

TL; DR:

local-storage-fallback.getItem(prop).setItem(prop, val)の統合API)を使用してください。

ブラウザ用の適切なストレージアダプタ(localStorage、sessionStorage、cookie、memory)を確認して使用します。

元の答え

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

AmplifyJSの場合

ローカルストレージ

  • IE 8以降
  • Firefox 3.5以降
  • サファリ4+
  • クロム
  • Opera 10.5以降
  • iPhone 2+
  • アンドロイド2+

sessionStorage

  • IE 8以降
  • Firefox 2以降
  • サファリ4+
  • クロム
  • Opera 10.5以降
  • iPhone 2+
  • アンドロイド2+

globalStorage

  • Firefox 2以降

userData

  • IE 5 - 7
  • userDataは、新しいバージョンのIEにも存在しますが、IE 9の実装には癖があるため、localStorageがサポートされている場合はuserDataを登録しません。

記憶

  • 他のストレージタイプが利用できない場合、インメモリストアが代替として提供されます。

PersistentJSの場合

  • flash:Flash 8の永続ストレージ.
  • gears:Google Gearsベースの永続ストレージ。
  • localstorage:HTML5ドラフトストレージ。
  • globalstorage:HTML 5ドラフトストレージ(古い仕様)。
  • 例:Internet Explorerのユーザーデータの動作。
  • cookie:cookieベースの永続的記憶域.

それらは抽象化レイヤを提供するので、あなたはストレージタイプを選ぶことについて心配する必要はありません。ただし、ストレージの種類によっては、サイズ制限などの制限がある場合があります。現在、私はAmplifyJSを使用していますが、それでもiOS 7/Safariなどでさらにテストを行う必要があります。それが実際に問題を解決するかどうか見るために。

2

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

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

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

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

2

2017年4月にパッチがSafariにマージされたため、他のブラウザと連携しました。これはSafari 11でリリースされました。

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

1
sandstrom

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

SignUp(attrs、options)関数はセッションを永続化するためにローカル記憶域を使用するため、ユーザーがプライベートブラウジングモードになっていると、 "QuotaExceededError:DOM Exception 22:クォータを超える記憶域に追加しようとしました"例外および成功/エラー関数は呼び出されません。

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

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

Javascript SDKリファレンスの解析https://parse.com/docs/js/api/classes/Parse.User.html#methods_signUp

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

0
clayostrom