[html] Safari의 html5 localStorage 오류 :“QUOTA_EXCEEDED_ERR : DOM 예외 22 : 할당량을 초과 한 저장소에 무언가를 추가하려고했습니다.”

내 웹 응용 프로그램에 iOS 사파리 개인 탐색에서 자바 스크립트 오류가 있습니다.

자바 스크립트 : 오류

찾으시는 주소가 없습니다

QUOTA_EXCEEDED_ERR : DOM 예외 22 : 저장소에 무언가를 추가하려고했습니다 …

내 코드 :

localStorage.setItem('test',1)



답변

분명히 이것은 의도적으로 설계된 것입니다. 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."

창 개체는 여전히 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;
    }
}


답변

위 링크에 게시 된 수정 프로그램이 작동하지 않았습니다. 이것은했다 :

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

http://m.cg/post/13095478393/detect-private-browsing-mode-in-mobile-safari-on-ios5 에서 파생 됨


답변

다른 답변에서 언급했듯이 localStorage.setItem(또는 sessionStorage.setItem)가 호출 되면 iOS 및 OS X의 Safari 개인 브라우저 모드에서 항상 QuotaExceededError 가 발생합니다.

한 가지 해결책 은를 사용하는 각 인스턴스에서 try / catch 또는 Modernizr 검사 를 수행하는 것 setItem입니다.

그러나이 오류가 전체적으로 중단되는 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.');
    }
}


답변

내 맥락에서 방금 클래스 추상화를 개발했습니다. 내 응용 프로그램이 시작되면 전화를 걸어 localStorage가 작동하는지 확인합니다. getStorage () . 이 함수는 다음도 반환합니다.

  • localStorage가 작동중인 경우 localStorage
  • 또는 커스텀 클래스의 구현 LocalStorageAlternative

내 코드에서는 localStorage를 직접 호출하지 않습니다. 나는 cusSto를 부른다 내가 호출하여 초기화 한 글로벌 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();


답변

Safari 11이 동작을 변경 한 것으로 보이며 이제 로컬 저장소가 개인 브라우저 창에서 작동합니다. 만세!

Safari 개인 브라우징에서 실패했던 웹 앱은 이제 완벽하게 작동합니다. 항상 Chrome의 비공개 브라우징 모드에서 정상적으로 작동하여 로컬 저장소에 항상 쓸 수있었습니다.

이 내용은 Apple의 Safari Technology Preview 릴리스 정보WebKit 릴리스 정보에 설명되어 있습니다. 2017 년 5 월 릴리스 29 에 설명되어 있습니다.

구체적으로 특별히:

  • 비공개 브라우징 모드 또는 WebDriver 세션에서 localStorage에 저장할 때 QuotaExceededError 수정 -r215315

답변

다른 사람들의 대답을 확장하기 위해 여기에 새로운 변수를 노출 / 추가하지 않는 소형 솔루션이 있습니다. 모든 기반을 다루지는 않지만 단일 페이지 앱만 작동 상태로 유지하려는 대부분의 사람들에게 적합해야합니다 (다시로드 후 데이터 지속성이 없어도).

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


답변

이온 프레임 워크 (Angular + Cordova)를 사용하여 동일한 문제가 발생했습니다. 나는 이것이 문제를 해결하지 못한다는 것을 알고 있지만 위의 답변을 기반으로 한 Angular Apps의 코드입니다. iOS 버전의 Safari에서 localStorage를위한 임시 솔루션이 제공됩니다.

코드는 다음과 같습니다.

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

출처 : https://gist.github.com/jorgecasar/61fda6590dc2bb17e871

코딩을 즐기십시오!