it-swarm.com.de

html5 localStorage-Fehler bei Safari: "QUOTA_EXCEEDED_ERR: DOM-Ausnahme 22: Es wurde versucht, etwas zum Speicher hinzuzufügen, der die Quote überschritten hat."

Meine Webapp hat Javascript-Fehler in der privaten Navigation von ios safari:

JavaScript: Fehler

undefined

QUOTA_EXCEEDED_ERR: DOM-Ausnahme 22: Es wurde versucht, etwas zum Speicher hinzuzufügen ...

mein code:

localStorage.setItem('test',1)
131
leiyonglin

Anscheinend ist das beabsichtigt. Wenn sich Safari (OS X oder iOS) im privaten Browsermodus befindet, scheint localStorage verfügbar zu sein. Der Aufruf von setItem löst jedoch eine Ausnahme aus.

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

Was passiert, ist, dass das Fensterobjekt noch localStorage im globalen Namespace verfügbar macht. Wenn Sie jedoch setItem aufrufen, wird diese Ausnahme ausgelöst. Alle Aufrufe von removeItem werden ignoriert.

Ich glaube, das einfachste Update (obwohl ich diesen Browser nicht getestet habe) wäre, die Funktion isLocalStorageNameSupported() zu ändern, um zu testen, ob Sie auch einen Wert festlegen können.

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

Das Update, das unter dem obigen Link veröffentlicht wurde, hat für mich nicht funktioniert. Dies tat:

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

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

37
cyberwombat

Wie in anderen Antworten erwähnt, erhalten Sie den QuotaExceededError im privaten Browser-Modus sowohl unter iOS als auch unter OS X, wenn localStorage.setItem (oder sessionStorage.setItem) aufgerufen wird.

Eine Lösung besteht darin, Try/Catch oder Modernizr Check in jeder Instanz von setItem auszuführen.

Wenn Sie jedoch ein Shim wünschen, das diesen Fehler einfach global verhindert, können Sie Folgendes verwenden, um zu verhindern, dass der Rest Ihres JavaScripts beschädigt wird.

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

In meinem Kontext habe ich gerade eine Klassenabstraktion entwickelt. Wenn ich meine Anwendung gestartet habe, überprüfe ich, ob localStorage funktioniert, indem ich getStorage () aufrufe. Diese Funktion gibt auch Folgendes zurück:

  • entweder localStorage, wenn localStorage funktioniert
  • oder eine Implementierung einer benutzerdefinierten Klasse LocalStorageAlternative

In meinem Code rufe ich localStorage nie direkt an. Ich rufe cusSto global var auf, das ich durch Aufruf von getStorage () initialisiert hatte.

Auf diese Weise funktioniert es beim privaten Surfen oder bei bestimmten Safari-Versionen

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();
11
Pierre Le Roux

Um die Antworten anderer zu erweitern, finden Sie hier eine kompakte Lösung, bei der keine neuen Variablen verfügbar gemacht werden. Es deckt nicht alle Grundlagen ab, sollte aber für die meisten Leute geeignet sein, die nur eine einzelne Seiten-App benötigen (obwohl keine Daten persistent sind).

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

Ich hatte das gleiche Problem bei der Verwendung von Ionic Framework (Angular + Cordova). Ich weiß, dass dies das Problem nicht löst, aber es ist der Code für Angular Apps, der auf den obigen Antworten basiert. Sie haben eine kurzlebige Lösung für localStorage auf der iOS-Version von Safari.

Hier ist der Code:

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

Quelle: https://Gist.github.com/jorgecasar/61fda6590dc2bb17e871

Viel Spaß beim Kodieren!

3
jorgecasar

Hier ist eine Lösung für AngularJS, die ein IIFE verwendet und die Tatsache ausnutzt, dass services Singletons sind.

Dies führt dazu, dass isLocalStorageAvailable sofort eingestellt wird, wenn der Service zum ersten Mal eingespeist wird, und es unnötig ist, die Prüfung jedes Mal durchzuführen, wenn auf den lokalen Speicher zugegriffen werden muss.

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

Ich habe gerade dieses repo erstellt, um die Funktionen sessionStorage und localStorage für nicht unterstützte oder deaktivierte Browser bereitzustellen.

Unterstützte Browser

  • IE5 +
  • Chrome alle Versionen
  • Mozilla alle Versionen
  • Yandex alle Versionen

Wie es funktioniert

Es erkennt die Funktion mit dem Speichertyp.

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

Legt StorageService.localStorage auf window.localStorage fest, wenn es unterstützt wird oder einen Cookie-Speicher erstellt Legt StorageService.sessionStorage auf window.sessionStorage fest, wenn es unterstützt wird, oder erstellt einen Speicher für SPA, Cookie-Speicher mit Sitzungsfunktionen für Nicht-SPA.

1

Es scheint, dass Safari 11 das Verhalten ändert, und lokaler Speicher funktioniert jetzt in einem privaten Browserfenster. Hurra!

Unsere Web-App, die bisher beim privaten Surfen von Safari fehlgeschlagen ist, funktioniert jetzt einwandfrei. Im privaten Browsing-Modus von Chrome hat es immer gut funktioniert. In diesem Modus wurde immer auf lokalen Speicher geschrieben.

Dies ist in den Versionshinweisen zu Apple Safari Technology Preview - und den WebKit-Versionshinweisen - für Version 29 (Mai 2017) dokumentiert. 

Speziell:

  • QuotaExceededError beim Speichern in localStorage im privaten Browsermodus oder in WebDriver-Sitzungen behoben - r215315
1
karlbecker_com

Verwenden Sie es nicht, wenn es nicht unterstützt wird. Um die Unterstützung zu prüfen, rufen Sie einfach diese Funktion auf

freigabe in Es6, Lesen und Schreiben von localStorage Beispiel mit Support-Prüfung

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

Dadurch wird sichergestellt, dass Ihre Schlüssel in allen Browsern richtig eingestellt und abgerufen werden.

0
Tarandeep Singh

Hier ist eine Angular2 + -Serviceversion für eine alternative Speicherkapazität, die Sie basierend auf der Antwort von Pierre Le Roux einfach in Ihre Komponenten einfügen können.

import { Injectable } from '@angular/core';

// Alternative to localstorage, memory
// storage for certain browsers in private mode
export class LocalStorageAlternative {
    private  structureLocalStorage = {};

    setItem(key: string, value: string): void {
        this.structureLocalStorage[key] = value;
    }

    getItem(key: string): string {
        if (typeof this.structureLocalStorage[key] !== 'undefined' ) {
            return this.structureLocalStorage[key];
        }
        return null;
    }

    removeItem(key: string): void {
        this.structureLocalStorage[key] = undefined;
    }
}

@Injectable()
export class StorageService {
    private storageEngine;

    constructor() {
        try {
            localStorage.setItem('storage_test', '');
            localStorage.removeItem('storage_test');
            this.storageEngine = localStorage;
        } catch (err) {
            this.storageEngine = new LocalStorageAlternative();
        }
    }

    setItem(key: string, value: string): void {
        this.storageEngine.setItem(key, value);
    }

    getItem(key: string): string {
        return this.storageEngine.getItem(key);
    }

    removeItem(key: string): void {
        this.storageEngine.removeItem(key);
    }

}
0
Gabriel Alack
var mod = 'test';
      try {
        sessionStorage.setItem(mod, mod);
        sessionStorage.removeItem(mod);
        return true;
      } catch (e) {
        return false;
      }
0
Naim DOGAN