Подтвердить что ты не робот

QuotaExceededError: исключение Dom 22: Была сделана попытка добавить что-то к хранилищу, которое превысило квоту

Использование LocalStorage на iPhone с iOS 7 вызывает эту ошибку. Я искал разрешения для резонатора, но, учитывая, что я даже не занимаюсь приватизацией, ничего не имеет значения.

Я не понимаю, почему localStorage будет отключен по умолчанию в iOS 7, но, похоже, это так? Я тестировал и другие сайты, но не повезло. Я даже попытался проверить его с помощью этого веб-сайта: http://arty.name/localstorage.html, но похоже, что он ничего не спасает по какой-то странной причине.

У кого-то была такая же проблема, только им посчастливилось это исправить? Должен ли я переключить метод хранения?

Я попытался отладить его, сохранив только несколько строк информации, но безрезультатно. Я использовал стандартную функцию localStorage.setItem() для сохранения.

4b9b3361

Ответ 1

Это может произойти, если Safari находится в режиме приватного режима. В частном браузере локальное хранилище вообще недоступно.

Одно из решений - предупредить пользователя о том, что приложение нуждается в не приватном режиме.

UPDATE: это было исправлено в Safari 11, поэтому поведение теперь выровнено с другими браузерами.

Ответ 2

Как уже упоминалось в других ответах, вы всегда получите QuotaExceededError в режиме приватного браузера Safari на iOS и OS X, когда вызывается localStorage.setItem (или sessionStorage.setItem).

Одним из решений является попытка try/catch или Проверка модернизма в каждом случае использования 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.');
    }
}

Ответ 3

Я использую эту простую функцию, которая возвращает true или 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')
}

Ответ 4

Мне довелось работать с той же проблемой в iOS 7 (с некоторыми устройствами нет симуляторов).

Похоже, что Safari в iOS 7 имеет более низкую квоту хранилища, которая, по-видимому, достигается за счет длинного журнала истории.

Я предполагаю, что лучшая практика будет заключаться в том, чтобы поймать исключение.

В проекте Modernizr есть простой патч, вы должны попробовать что-то подобное: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js

Ответ 5

Вот расширенное решение на основе ответа DrewT выше, в котором используются файлы cookie, если localStorage недоступен. Он использует 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' );
...

Ответ 6

Как уже объяснялось в других ответах, в режиме приватного просмотра Safari всегда будет генерировать это исключение при попытке сохранить данные с помощью localStorage.setItem().

Чтобы исправить это, я написал поддельный localStorage, который имитирует localStorage, как методы, так и события.

Fake localStorage: https://gist.github.com/engelfrost/fd707819658f72b42f55

Это, вероятно, не является хорошим общим решением проблемы. Это было хорошим решением для моего сценария, где альтернатива была бы серьезной перезаписи в уже существующее приложение.

Ответ 7

Чтобы добавить к предыдущим ответам, одним из возможных способов решения проблемы было бы изменить метод хранения. Есть несколько librairies, таких как AmplifyJS и PersistJS которые могут помочь. Обе библиотеки позволяют хранить постоянное клиентское хранилище через несколько бэкэндов.

Для 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 мы не регистрируем userData, если localStorage поддерживается.

памяти

  • Хранилище в памяти предоставляется в качестве резервной копии, если ни один из других типов хранения не доступен.

Для PersistentJS

  • flash: постоянное хранилище Flash 8.
  • gears: постоянное хранилище на основе Google Gears.
  • localstorage: хранилище черновиков HTML5.
  • globalstorage: хранилище черновиков HTML5 (старая спецификация).
  • то есть: поведение пользовательских данных в Internet Explorer.
  • cookie: постоянное хранилище на основе файлов cookie.

Они предлагают слой абстракции, поэтому вам не нужно беспокоиться о выборе типа хранилища. Помните, что в зависимости от типа хранилища могут быть некоторые ограничения (например, ограничения размера). Прямо сейчас, я использую AmplifyJS, но мне еще нужно сделать еще несколько тестов на iOS 7/Safari/etc. чтобы узнать, действительно ли это решает проблему.

Ответ 8

В апреле 2017 года патч был объединен в Safari, поэтому он выровнялся с другими браузерами. Это было выпущено с Safari 11.

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

Ответ 9

Этот вопрос и ответ помогли мне решить конкретную проблему с подпиской новых пользователей в Parse.

Поскольку функция signUp (attrs, options) использует локальное хранилище для сохранения сеанса, если пользователь находится в режиме приватного просмотра, он выбрасывает "QuotaExceededError: DOM Exception 22". Была сделана попытка добавить что-то к хранилищу, которое превысило квота ". исключение и функции успеха/ошибки никогда не вызываются.

В моем случае, поскольку функция ошибки никогда не вызывается, изначально казалось, что это проблема с запуском события click на отправке или перенаправлении, определенных при успешном подписании.

Включение предупреждения для пользователей разрешило проблему.

Параметр Javascript SDK Reference https://parse.com/docs/js/api/classes/Parse.User.html#methods_signUp

Подписывает нового пользователя с именем пользователя (или электронной почтой) и паролем. Это создаст новый сервер Parse.User на сервере , а также сохранит сеанс в localStorage, чтобы вы могли получить доступ к пользователю с помощью {@link #current}.