QuotaExceededError: Dom istisnası 22: Depolama alanına kotayı aşan bir şey eklenmeye çalışıldı


219

İOS 7 ile iPhone'da LocalStorage kullanmak bu hatayı atar. Bir çözüm aradım, ama özel olarak göz atmadığımı düşünürsek, hiçbir şey ilgili değil.

İOS 7'de localStorage'ın neden varsayılan olarak devre dışı bırakılacağını anlamıyorum, ama öyle görünüyor? Diğer web sitelerinde de test ettim, ama hiç şansım yok. Hatta bu web sitesini kullanarak test etmeyi denedim: http://arty.name/localstorage.html , ama garip bir nedenden dolayı hiçbir şey kaydetmiyor gibi görünmüyor.

Herkes aynı problemi yaşadı mı, sadece düzeltmekte şansları oldu mu? Depolama yöntemimi değiştirmeli miyim?

Sadece birkaç satır bilgi depolayarak hata ayıklamayı denedim, ancak boşuna. localStorage.setItem()Kaydetmek için standart işlevi kullandım.


2
Bu genellikle kullanılabilir depolama alanını aşan boyutta bir şey depolamaya çalıştığınız anlamına gelir. Hangi tarayıcıyı kullanıyorsunuz (Safari, Chrome vb.)? Kullandığınız kodu ve mümkünse depolamaya çalıştığınız verileri biraz daha paylaşabilir misiniz?

3
Bu, Safari tarafında bir hata veya sorun olarak düşünülmelidir.
LocalStorage'ı

Bu sorun için test yapan bir özellik algılama kullanın . Depolama yoksa, localStorage'ı memoryStorage ile küçültmeyi düşünün . yasal uyarı: Bağlantılı paketlerin
yazarıyım

1
Nisan 2017'de bir yama Safari'ye birleştirildi, bu yüzden diğer tarayıcılarla hizalandı. Muhtemelen Safari 11'e inecek. Bugs.webkit.org/show_bug.cgi?id=157010
sandstrom

2
Bunun Safari iOS 11'de düzeltildiğini onaylayabilirim. Test edilmiş Özel tarama + sessionStorage.setItem () ve sonra sessionStorage.getItem () başarıyla iPhone6 ​​ve iPhone8'de.
Kevin Gaudin

Yanıtlar:


372

Bu, Safari özel modda göz atarken gerçekleşebilir. Özel tarama sırasında yerel depolama hiç kullanılamaz.

Bir çözüm, kullanıcıyı uygulamanın çalışması için özel olmayan moda ihtiyaç duyduğu konusunda uyarmaktır.

GÜNCELLEME: Bu, Safari 11'de düzeltildi , bu nedenle davranış artık diğer tarayıcılarla hizalandı.


4
Yayınınız bugün benim için inanılmaz derecede yararlı ve zamanındaydı (24 saatten kısa bir süre sonra). Referans olarak, özel göz atmayı nasıl açıp kapatacağınız aşağıda açıklanmıştır
Nick

12
+1 sorunumu düzeltti. if( typeof Storage != 'undefined' ) { ... }Bilgi yüklemeye ve kaydetmeye ama bu hatayı almadan önce LocalStorage ( ) varlığını kontrol ediyordum . Çıkıyor Storagehala kullanışsız olsa bile tanımlanır. LocalStorage'ı her kullandığımda bundan sonra dene / yakala özelliğini kullanıyorum.
stevendesu

Teşekkürler! Safari tarafından garip bir hata. Daha bilgilendirici olmalıydı. : D
Sunny R Gupta

2
Safari Tech Preview 29'dan itibaren bir düzeltme geliyor olabilir: "Özel tarama modunda veya WebDriver oturumlarında localStorage'a kaydederken Sabit QuotaExceededError". Bkz developer.apple.com/safari/technology-preview/release-notes
Marc BAUMBACH

1
Bu, örneğin görüntüler kaydedilerek kolayca yapılabilen depolama sınırına ulaşıldığında da ortaya çıkabilir .
csalmeida

103

Diğer yanıtlarda belirtildiği gibi, localStorage.setItem(veya sessionStorage.setItem) çağrıldığında her zaman hem iOS hem de OS X'te Safari Özel Tarayıcı Modunda QuotaExceededError alırsınız .

Bir çözüm, her kullanım örneğinde bir try / catch veya Modernizr kontrolü yapmaktır setItem.

Ancak, JavaScript'in geri kalanının bozulmasını önlemek için, bu hatanın küresel olarak atılmasını durduran bir dolgu istiyorsanız, bunu kullanabilirsiniz:

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
Yine de kullanmayacaksanız neden setItem'i Storage nesnesine eklemelisiniz?
Necromancer

4
Snippet'imin amacı, uygulamanızın Safari özel modunda tamamen kırılmamasını istiyorsanız JS hatalarının atılmasını görmezden gelmektir.
philfreo

16

LocalStorage kullanılabilirliğini sınamak için dönen trueveya bu basit işlevi kullanın false:

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

Şimdi localStorage.setItem()kullanmadan önce kullanılabilirliğini test edebilirsiniz . Misal:

if ( isLocalStorageNameSupported() ) {
    // can use localStorage.setItem('item','value')
} else {
    // can't use localStorage.setItem('item','value')
}

Bir şey kaçırdım mı? Neden çağrılan bir yöntem window.sessionStorageyerine kullanılıyor ? window.localStorageisLocalStorageNameSupported
Mart'ta Ithar

@lthar - buradaki belgelere bakın: w3schools.com/html/html5_webstorage.asp En önemlisi bu bölüm: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, ancak test anahtarınızı kaldırırsanız bu durumdaki fark nedir? Silebileceğim takdirde test anahtarımı nerede saklayacağım önemli değil. Yanlış mıyım? Oturum depolama alanı neden yerel depolama alanından daha iyi?
Vladyslav Turak

1
@TurakVladyslav haklısın, burada gerçekten bir fark yok, ancak sessionStoragegelişiminizi test etmek istiyorsanız kesme noktalarını ayarlamak için daha yönetilebilir hale getirmek dışında . Bunun "daha iyi" olduğu konusunda gerçek bir argüman yoktur ve burada dikkat edilmesi gereken sadece kişisel bir tercihtir. Nota Önemli olan hem olmasıdır sessionStorageve localStorageHTML5 WebStorage API hem uygulamaları bulunmaktadır.
DrewT


3

LocalStorage kullanılamıyorsa, DrewT'nin yukarıdaki cevabı temel alan genişletilmiş bir çözüm. Mozilla'nın docCookies kütüphanesini kullanır :

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

Kaynağınızda şunları kullanın:

localStorageSet( 'foobar', 'yes' );
...
var foo = localStorageGet( 'foobar' );
...

2

Diğer yanıtlarda açıklandığı gibi , Özel Tarama modunda Safari, verileri kaydetmeye çalışırken her zaman bu istisnayı atar localStorage.setItem().

Bunu düzeltmek için localStorage'ı taklit eden sahte bir localStorage yazdım, hem yöntemler hem de olaylar.

Sahte yerel Depolama: https://gist.github.com/engelfrost/fd707819658f72b42f55

Bu muhtemelen soruna iyi bir genel çözüm değildir. Bu, alternatifimin zaten var olan bir uygulamaya yeniden yazacağı senaryom için iyi bir çözümdü.


Tam olarak ne düzeltiyor? Hiçbir şey devam etmiyor, ne anlamı var?
Esben Skov Pedersen

1
Özel tarama modunda Safari'yi "düzeltir". (Bu cevabımda net değil, belirttiğiniz için teşekkürler. Cevabımı düzenleyeceğim). Özel tarama modundayken hiçbir şeyin devam edeceği varsayılmaz, bu nedenle devam etmemek burada ilgili bir sorun değildir. Bunun benim için düzelttiği şey, kullanıcıların Safari'deki Özel Tarama modundayken bile büyük bir yeniden yazma olmadan mevcut bir uygulamayı çalıştırmasına izin vermekti.
Josef Engelfrost

2

Güncelleme (2016-11-01)

Bu soruna geçici bir çözüm bulmak için aşağıda belirtilen AmplifyJS kullanıyordum. Ancak, Safari'de Gizli tarama için bellek tabanlı bir depolamaya geri dönüyordu. Benim durumumda, bu uygun değildi çünkü kullanıcı hala özel taramada olsa bile depolamanın yenilenme sırasında temizlendiği anlamına geliyor.

Ayrıca, iOS Safari'de her zaman Özel modda dolaşan birkaç kullanıcı fark ettim. Bu nedenle, Safari için daha iyi bir geri dönüş çerezleri (varsa) kullanmaktır. Varsayılan olarak, çerezler gizli taramada bile erişilebilir. Tabii ki, özel taramadan çıktıklarında temizlenirler, ancak yenileme sırasında temizlenmezler.

Local-storage-fallback kütüphanesini buldum . Belgelerden:

amaç

"Özel Tarama" gibi tarayıcı ayarlarında, yeni tarayıcılarda bile çalışan bir window.localStorage'a güvenmek bir sorun haline gelmiştir. Var olmasına rağmen, setItem veya getItem kullanmaya çalışırken istisnalar atacaktır. Bu modül, hangi tarayıcı depolama mekanizmasının kullanılabileceğini görmek için uygun kontrolleri çalıştıracak ve sonra ortaya çıkaracaktır. LocalStorage ile aynı API'yı kullanır, bu nedenle çoğu durumda bir yedek değiştirme olarak çalışmalıdır.

Gotchas dikkat:

  • CookieStorage'ın depolama sınırları vardır. Burada dikkatli ol.
  • MemoryStorage sayfa yüklemeleri arasında kalmayacak. Bu, sayfa kilitlenmelerini önlemek için aşağı yukarı bir boşluktur, ancak tam sayfa yüklemesi yapmayan web siteleri için yeterli olabilir.

TL; DR:

Kullanım yerel depolama yedeği (ile birleşik API .getItem(prop)ve .setItem(prop, val)):

Tarayıcı için uygun depolama adaptörünü kontrol edin ve kullanın (localStorage, sessionStorage, çerezler, bellek)

Orijinal cevap

Önceki yanıtlara eklemek için olası bir çözüm depolama yöntemini değiştirmek olacaktır. AmplifyJS ve PersistJS gibi yardımcı olabilecek birkaç kütüphaneci vardır . Her iki kütük de birkaç arka uç aracılığıyla kalıcı istemci tarafında depolamaya izin verir.

AmplifyJS için

yerel depolama

  • IE 8+
  • Firefox 3.5 ve üzeri
  • Safari 4+
  • Krom
  • Opera 10.5 ve üstü
  • iPhone 2+
  • Android 2 ve üstü

sessionStorage

  • IE 8+
  • Firefox 2+
  • Safari 4+
  • Krom
  • Opera 10.5 ve üstü
  • iPhone 2+
  • Android 2 ve üstü

globalStorage

  • Firefox 2+

Kullanıcı bilgisi

  • IE 5-7
  • userData, IE'nin yeni sürümlerinde de mevcuttur, ancak IE 9'un uygulamasındaki tuhaflıklar nedeniyle, localStorage destekleniyorsa userData'yı kaydetmiyoruz.

hafıza

  • Diğer depolama türlerinden hiçbiri yoksa bellek içi bir depo yedek olarak sağlanır.

Kalıcı JS için

  • flash: Flash 8 kalıcı depolama.
  • Dişliler: Google Gears tabanlı kalıcı depolama.
  • localstorage: HTML5 taslak depolama.
  • globalstorage: HTML5 taslak depolama (eski özellikler).
  • ie: Internet Explorer kullanıcı veri davranışları.
  • çerez: Çerez tabanlı kalıcı depolama.

Depolama türünü seçme konusunda endişelenmenize gerek kalmayacak şekilde bir soyutlama katmanı sunarlar. Ancak depolama türüne bağlı olarak bazı sınırlamalar (boyut sınırları gibi) olabileceğini unutmayın. Şu anda AmplifyJS kullanıyorum, ancak yine de iOS 7 / Safari / vb. Üzerinde biraz daha test yapmak zorundayım. Sorunu gerçekten çözüp çözmediğini görmek için.


Editör John: Sizin ve Jonathan Alzetta'nın muhtemelen aynı hesap olduğunun farkındayım ve sadece cevabınızı geliştirmeye çalışıyorsunuz, ancak eğer öyleyse gerçekten Jonathan Alzetta olarak giriş yapmalı ve bu cevabı düzenlemelisiniz ve sonra geçmeyecek inceleme kuyruğu. Gerekirse hesabınızı kurtarın.
DavidS


0

Bu soru ve cevap, Parse'de yeni kullanıcılara kaydolmayla ilgili belirli bir sorunu çözmeme yardımcı oldu.

SignUp (attrs, options) işlevi oturumu devam ettirmek için yerel depolama kullandığından, bir kullanıcı özel tarama modundaysa "QuotaExceededError: DOM Özel Durum 22: Depolama alanına kotayı aşan bir şey eklenmeye çalışıldı." istisna ve başarı / hata işlevleri asla çağrılmaz.

Benim durumumda, hata fonksiyonu asla çağrılmadığından, başlangıçta gönderime tıklama olayını veya kaydolma başarısında tanımlanan yönlendirmeyi tetiklemeyle ilgili bir sorun olduğu ortaya çıktı.

Kullanıcılar için bir uyarı eklemek sorunu çözdü.

Javascript SDK Referansını Ayrıştırma https://parse.com/docs/js/api/classes/Parse.User.html#methods_signUp

Yeni bir kullanıcıyı bir kullanıcı adı (veya e-posta) ve şifreyle kaydeder. Bu sunucuda yeni bir Parse.User oluşturur ve {@link #current} kullanarak kullanıcıya erişebilmeniz için localStorage'daki oturumu devam ettirir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.