QuotaExceededError: ข้อยกเว้น Dom 22: มีความพยายามในการเพิ่มบางสิ่งบางอย่างในที่เก็บข้อมูลที่เกินโควต้า


219

การใช้ LocalStorage บน iPhone กับ iOS 7 ทำให้เกิดข้อผิดพลาดนี้ ฉันได้ดูรอบ ๆ ตัวแก้ไขปัญหา แต่เมื่อพิจารณาว่าฉันไม่ได้ท่องเว็บแบบส่วนตัวไม่มีอะไรเกี่ยวข้องเลย

ฉันไม่เข้าใจว่าเหตุใด localStorage จึงถูกปิดใช้งานโดยค่าเริ่มต้นใน iOS 7 แต่ดูเหมือนว่าเป็นเพราะอะไร ฉันได้ทดสอบกับเว็บไซต์อื่นแล้วเช่นกัน แต่ไม่มีโชค ฉันลองทดสอบโดยใช้เว็บไซต์นี้: http://arty.name/localstorage.htmlแต่ดูเหมือนว่ามันจะไม่บันทึกอะไรเลยด้วยเหตุผลแปลก ๆ

มีใครมีปัญหาเดียวกันมีเพียงพวกเขาที่โชคดีเท่านั้น ฉันควรเปลี่ยนวิธีการจัดเก็บของฉัน?

ฉันพยายามแก้จุดบกพร่องโดยเก็บข้อมูลเพียงไม่กี่บรรทัด แต่ก็ไม่มีประโยชน์ ฉันใช้localStorage.setItem()ฟังก์ชั่นมาตรฐานเพื่อบันทึก


2
โดยปกติจะหมายถึงคุณพยายามจัดเก็บบางอย่างที่มีขนาดเกินพื้นที่จัดเก็บที่ว่าง คุณใช้เบราว์เซอร์ใด (Safari, Chrome, ฯลฯ ) คุณช่วยแบ่งปันรหัสที่คุณใช้ไปอีกหน่อยได้ไหมและถ้าเป็นไปได้ข้อมูลที่คุณพยายามจะจัดเก็บ

3
สิ่งนี้ควรได้รับการพิจารณาว่าเป็นข้อผิดพลาดหรือปัญหาในด้าน Safari มันไม่ได้ทำให้รู้สึกว่าคุณไม่สามารถใช้ localStorage ในโหมดไม่ระบุตัวตน ...
Maksim Luzik

ใช้คุณลักษณะการตรวจสอบการทดสอบว่าสำหรับปัญหานี้โดยเฉพาะ ถ้าการจัดเก็บไม่สามารถใช้ได้พิจารณา shimming localStorage กับmemoryStorage ปฏิเสธความรับผิดชอบ: ฉันเป็นผู้เขียนของแพคเกจที่เชื่อมโยง
Stijn de Witt

1
ในเดือนเมษายน 2560 มีการรวมโปรแกรมแก้ไขเข้าไปใน Safari ดังนั้นจึงสอดคล้องกับเบราว์เซอร์อื่น มีแนวโน้มว่าจะลงจอดใน Safari 11. bugs.webkit.org/show_bug.cgi?id=157010
sandstrom

2
ฉันสามารถยืนยันสิ่งนี้ได้รับการแก้ไขใน Safari iOS 11 ผ่านการทดสอบการท่องเว็บแบบส่วนตัว + sessionStorage.setItem () จากนั้น sessionStorage.getItem () สำเร็จใน iPhone6 ​​และ iPhone8
Kevin Gaudin

คำตอบ:


372

สิ่งนี้สามารถเกิดขึ้นได้เมื่อ Safari อยู่ในโหมดเรียกดูส่วนตัว ขณะเรียกดูแบบส่วนตัวพื้นที่จัดเก็บในตัวเครื่องไม่สามารถใช้งานได้ทั้งหมด

ทางออกหนึ่งคือเตือนผู้ใช้ว่าแอปนั้นต้องการโหมดที่ไม่ใช่ส่วนตัวในการทำงาน

UPDATE: สิ่งนี้ได้รับการแก้ไขในSafari 11ดังนั้นขณะนี้ลักษณะการทำงานจะสอดคล้องกับเบราว์เซอร์อื่น


4
โพสต์ของคุณเป็นประโยชน์อย่างเหลือเชื่อและทันเวลาสำหรับฉันในวันนี้ (น้อยกว่า 24 ชั่วโมงภายหลัง) สำหรับการอ้างอิงต่อไปนี้เป็นวิธีเปิด / ปิดการเรียกดูแบบส่วนตัว: imore.com/how-use-private-browsing-ios-7-safari
นิค

12
+1 แก้ไขปัญหาของฉัน ฉันตรวจสอบการมีอยู่ของ LocalStorage ( if( typeof Storage != 'undefined' ) { ... }) ก่อนที่จะพยายามโหลดและบันทึกข้อมูล แต่ได้รับข้อผิดพลาดนี้ เปิดใช้งานStorageยังคงถูกกำหนดแม้ในกรณีที่ไม่สามารถใช้งานได้ ใช้ลอง / จับจากนี้ไปเมื่อใดก็ตามที่ฉันใช้ LocalStorage
stevendesu

ขอบคุณ! ข้อผิดพลาดแปลก ๆ โดยซาฟารี ควรได้รับข้อมูลมากขึ้น : D
Sunny R Gupta

2
การแก้ไขอาจเข้ามาในขณะที่ Safari Tech Preview 29: "แก้ไข QuotaExceededError เมื่อบันทึกลงใน localStorage ในโหมดการท่องเว็บแบบส่วนตัวหรือเซสชัน WebDriver" ดูdeveloper.apple.com/safari/technology-preview/release-notes
Marc Baumbach

1
สิ่งนี้สามารถเกิดขึ้นได้หากถึงขีด จำกัด ของพื้นที่เก็บข้อมูลซึ่งสามารถทำได้อย่างง่ายดายโดยการบันทึกรูปภาพ
csalmeida

103

ตามที่กล่าวไว้ในคำตอบอื่น ๆ คุณจะได้รับ QuotaExceededError ใน Safari Private Browser Mode ทั้งใน iOS และ OS X เมื่อมีการเรียกlocalStorage.setItem(หรือsessionStorage.setItem)

ทางออกหนึ่งคือการทำลอง / จับหรือตรวจสอบ ModernizrsetItemในกรณีของการใช้แต่ละ

อย่างไรก็ตามหากคุณต้องการชิมที่ทั่วโลกเพียงแค่หยุดข้อผิดพลาดนี้จะถูกโยนเพื่อป้องกันไม่ให้ส่วนที่เหลือของ 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.');
    }
}

1
เหตุใดจึงเพิ่ม setItem ไปยังวัตถุหน่วยเก็บข้อมูลหากคุณไม่สามารถใช้งานได้
หมอผี

4
จุดตัวอย่างของฉันคือการละเว้นข้อผิดพลาด JS จากการถูกโยนถ้าคุณต้องการให้แอปของคุณไม่แตกในโหมดส่วนตัวของ Safari
philfreo

16

ฉันใช้ฟังก์ชั่นง่าย ๆ นี้ซึ่งผลตอบแทน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')
}

ฉันพลาดอะไรไปหรือเปล่า ทำไมwindow.sessionStorageถูกนำมาใช้แทนwindow.localStorageวิธีการที่เรียกว่าisLocalStorageNameSupported?
Ithar

@lthar - ดูเอกสารที่นี่: w3schools.com/html/html5_webstorage.aspสิ่งสำคัญที่สุดในส่วนนี้: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 แต่ความแตกต่างในสถานการณ์นี้คืออะไรถ้าคุณลบรหัสทดสอบของคุณ ไม่สำคัญว่าฉันจะเก็บรหัสทดสอบไว้ที่ไหนถ้าฉันจะลบทิ้ง ฉันผิดหรือเปล่า? เหตุใดการจัดเก็บเซสชันจึงดีกว่าที่เก็บข้อมูลภายใน
Vladyslav Turak

1
@TurakVladyslav คุณอยู่ที่นั่นจริงๆแล้วมันไม่แตกต่างไปจากที่นี่ยกเว้นว่าการใช้sessionStorageทำให้จัดการจุดพักได้ง่ายขึ้นถ้าคุณต้องการทดสอบการพัฒนาของคุณ ไม่มีการโต้แย้งที่แท้จริงซึ่งเป็น "ดีกว่า" และเป็นเพียงการตั้งค่าส่วนตัวที่นี่ที่ผิดด้านของความระมัดระวัง สิ่งสำคัญที่ควรทราบก็คือทั้งคู่sessionStorageและlocalStorageเป็นการนำ API5 ของ HTML5 webstorage ไปใช้
DrewT

5

ฉันเกิดปัญหาในการทำงานกับปัญหาเดียวกันใน iOS 7 (โดยบางอุปกรณ์ไม่มีอุปกรณ์จำลอง)

ดูเหมือนว่า Safari ใน iOS 7 จะมีโควต้าการจัดเก็บข้อมูลที่ต่ำกว่าซึ่งเห็นได้ชัดว่าเข้าถึงได้ด้วยการบันทึกประวัติอันยาวนาน

ฉันเดาว่าวิธีปฏิบัติที่ดีที่สุดคือการยกเว้น

โครงการ Modernizr มีแพตช์ง่ายคุณควรลองทำสิ่งที่คล้ายกัน: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js


3

นี่คือวิธีแก้ปัญหาแบบขยายตามคำตอบของ DrewT ด้านบนที่ใช้คุกกี้หาก localStorage ไม่สามารถใช้ได้ ใช้ไลบรารี docCookiesของ Mozilla :

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

2

ตามที่ได้อธิบายไว้แล้วในคำตอบอื่น ๆเมื่ออยู่ในโหมดดูเว็บแบบส่วนตัว Safari จะเสมอlocalStorage.setItem()โยนข้อยกเว้นนี้เมื่อพยายามที่จะบันทึกข้อมูลด้วย

ในการแก้ไขปัญหานี้ฉันได้เขียน localStorage ปลอมที่เลียนแบบ localStorage ทั้งวิธีการและเหตุการณ์

ปลอม localStorage: https://gist.github.com/engelfrost/fd707819658f72b42f55

นี่อาจไม่ใช่วิธีแก้ไขปัญหาทั่วไปที่ดี นี่เป็นวิธีแก้ปัญหาที่ดีสำหรับสถานการณ์ของฉันซึ่งทางเลือกน่าจะเป็น re-write ที่สำคัญไปยังแอปพลิเคชันที่มีอยู่แล้ว


มันแก้ไขอะไรกันแน่? มันไม่ยืนยันอะไรเลยดังนั้นประเด็นคืออะไร
Esben Skov Pedersen

1
มัน "แก้ไข" Safari เมื่ออยู่ในโหมดเรียกดูส่วนตัว (นี่ไม่ชัดเจนในคำตอบของฉันขอบคุณสำหรับการชี้ให้เห็นว่าฉันจะแก้ไขคำตอบของฉัน) ไม่มีสิ่งใดที่ควรจะคงอยู่เมื่ออยู่ในโหมดการเรียกดูแบบส่วนตัวโดยไม่คำนึงถึงดังนั้นการคงอยู่ต่อไปจึงไม่ใช่ปัญหาที่เกี่ยวข้องที่นี่ สิ่งนี้ได้รับการแก้ไขสำหรับฉันคือการอนุญาตให้ผู้ใช้เรียกใช้แอปพลิเคชันที่มีอยู่แล้วโดยไม่ต้องมีการเขียนซ้ำที่สำคัญแม้ในโหมดการดูเว็บส่วนตัวใน Safari
Josef Engelfrost

2

อัปเดต (2016-11-01)

ฉันใช้ AmplifyJS ที่กล่าวถึงด้านล่างเพื่อแก้ไขปัญหานี้ อย่างไรก็ตามสำหรับ Safari ในการเรียกดูแบบส่วนตัวมันก็กลับไปที่หน่วยความจำที่ใช้หน่วยความจำ ในกรณีของฉันมันไม่เหมาะสมเพราะมันหมายถึงที่เก็บข้อมูลถูกล้างเมื่อรีเฟรชแม้ว่าผู้ใช้จะยังคงอยู่ในการเรียกดูแบบส่วนตัว

นอกจากนี้ฉันยังสังเกตเห็นผู้ใช้จำนวนมากที่มักเรียกดูในโหมดส่วนตัวบน iOS Safari ด้วยเหตุผลดังกล่าวทางเลือกที่ดีกว่าสำหรับ Safari คือการใช้คุกกี้ (หากมี) ตามค่าเริ่มต้นคุกกี้ยังคงสามารถเข้าถึงได้แม้ในการเบราส์ส่วนตัว แน่นอนว่าพวกเขาจะถูกล้างเมื่อออกจากการเรียกดูแบบส่วนตัว แต่จะไม่ถูกล้างเมื่อรีเฟรช

ฉันพบไลบรารีlocal-storage-fallback จากเอกสาร:

วัตถุประสงค์

ด้วยการตั้งค่าเบราว์เซอร์เช่น "การดูเว็บแบบส่วนตัว" มันกลายเป็นปัญหาที่ต้องพึ่งพาหน้าต่างที่ใช้งานได้การจัดเก็บข้อมูลแม้กระทั่งในเบราว์เซอร์ใหม่ แม้ว่ามันอาจมีอยู่ แต่มันจะโยนข้อยกเว้นเมื่อพยายามใช้ setItem หรือ getItem โมดูลนี้จะเรียกใช้การตรวจสอบที่เหมาะสมเพื่อดูว่ากลไกการจัดเก็บข้อมูลของเบราว์เซอร์ใดที่อาจพร้อมใช้งานจากนั้นจึงเปิดเผย มันใช้ API เดียวกับ localStorage ดังนั้นจึงควรใช้แทนการดรอปอินในกรณีส่วนใหญ่

ระวังของ gotchas:

  • CookieStorage มีพื้นที่ จำกัด ระวังที่นี่
  • MemoryStorage จะไม่คงอยู่ระหว่างการโหลดหน้า นี่เป็นช่องว่างหยุดมากขึ้นหรือน้อยลงเพื่อป้องกันการล่มของหน้า แต่อาจเพียงพอสำหรับเว็บไซต์ที่ไม่โหลดเต็มหน้า

TL; DR:

ใช้local-storage-fallback (unified API ด้วย.getItem(prop)และ.setItem(prop, val)):

ตรวจสอบและใช้อะแดปเตอร์หน่วยเก็บข้อมูลที่เหมาะสมสำหรับเบราว์เซอร์ (localStorage, sessionStorage, คุกกี้, หน่วยความจำ)

คำตอบเดิม

เพื่อเพิ่มตามคำตอบก่อนหน้าหนึ่งวิธีแก้ปัญหาที่เป็นไปได้หนึ่งคือการเปลี่ยนวิธีการจัดเก็บ มีการสักสองสามอย่างเช่นAmplifyJSและPersistJSที่สามารถช่วยได้ libs ทั้งสองอนุญาตการจัดเก็บข้อมูลฝั่งไคลเอ็นต์แบบถาวรผ่านแบ็กเอนด์หลาย ๆ

สำหรับ AmplifyJS

localStorage

  • IE 8+
  • Firefox 3.5+
  • Safari 4+
  • โครเมียม
  • Opera 10.5+
  • iPhone 2+
  • Android 2+

sessionStorage

  • IE 8+
  • Firefox 2+
  • Safari 4+
  • โครเมียม
  • Opera 10.5+
  • iPhone 2+
  • Android 2+

globalStorage

  • Firefox 2+

UserData

  • IE 5 - 7
  • userData มีอยู่ใน IE เวอร์ชั่นใหม่กว่าเช่นกัน แต่เนื่องจากพฤติกรรมในการใช้งาน IE 9 เราจึงไม่ลงทะเบียน userData หากรองรับ localStorage

หน่วยความจำ

  • ที่เก็บในหน่วยความจำมีให้เป็นทางเลือกหากไม่มีประเภทการจัดเก็บอื่น ๆ

สำหรับ PersistentJS

  • แฟลช: แฟลช 8 ที่เก็บข้อมูลถาวร
  • gears: ที่เก็บข้อมูลถาวรบน Google Gears
  • localstorage: ที่เก็บแบบร่าง HTML5
  • globalstorage: ที่เก็บแบบร่าง HTML5 (ข้อมูลจำเพาะเก่า)
  • เช่นพฤติกรรมผู้ใช้ Internet Explorer
  • คุกกี้: ที่เก็บข้อมูลถาวรแบบอิงคุกกี้

พวกมันมีเลเยอร์ที่เป็นนามธรรมดังนั้นคุณไม่ต้องกังวลกับการเลือกประเภทของที่เก็บข้อมูล โปรดทราบว่าอาจมีข้อ จำกัด บางอย่าง (เช่น จำกัด ขนาด) ขึ้นอยู่กับประเภทของที่เก็บข้อมูล ตอนนี้ฉันกำลังใช้ AmplifyJS แต่ฉันยังต้องทำการทดสอบเพิ่มเติมใน iOS 7 / Safari / ฯลฯ เพื่อดูว่าจริงแก้ปัญหา


บรรณาธิการจอห์น: ฉันรู้ว่าคุณและ Jonathan Alzetta อาจเป็นบัญชีเดียวกันและคุณเพียงแค่พยายามปรับปรุงคำตอบของคุณ แต่ถ้าเป็นเช่นนั้นคุณควรเข้าสู่ระบบในฐานะ Jonathan Alzetta และแก้ไขคำตอบนี้แล้วมันจะไม่ผ่าน คิวการตรวจสอบ กู้คืนบัญชีของคุณหากคุณต้องการ
DavidS

1

ในเดือนเมษายน 2560 มีการรวมโปรแกรมแก้ไขเข้าไปใน Safari ดังนั้นจึงสอดคล้องกับเบราว์เซอร์อื่น เรื่องนี้ได้รับการปล่อยตัวด้วย Safari 11

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


0

คำถามและคำตอบนี้ช่วยฉันแก้ปัญหาเฉพาะด้วยการลงทะเบียนผู้ใช้ใหม่ในการแยกวิเคราะห์

เนื่องจากฟังก์ชั่น signUp (attrs, options) ใช้ที่จัดเก็บในตัวเครื่องเพื่อคงเซสชันหากผู้ใช้อยู่ในโหมดการท่องเว็บแบบส่วนตัวมันจะส่งข้อความ "QuotaExceededError: DOM Exception 22: มีความพยายามในการเพิ่มบางอย่างลงในที่จัดเก็บเกินโควต้า" ข้อยกเว้นและฟังก์ชันความสำเร็จ / ข้อผิดพลาดจะไม่ถูกเรียก

ในกรณีของฉันเพราะฟังก์ชั่นข้อผิดพลาดไม่เคยถูกเรียกว่ามันเริ่มปรากฏว่ามีปัญหากับการยิงเหตุการณ์คลิกในการส่งหรือการเปลี่ยนเส้นทางที่กำหนดไว้ในความสำเร็จของการสมัคร

รวมถึงคำเตือนสำหรับผู้ใช้ในการแก้ไขปัญหา

แยกวิเคราะห์ Javascript SDK อ้างอิง https://parse.com/docs/js/api/classes/Parse.User.html#methods_signUp

ลงทะเบียนผู้ใช้ใหม่ด้วยชื่อผู้ใช้ (หรืออีเมล) และรหัสผ่าน สิ่งนี้จะสร้าง Parse.User ใหม่บนเซิร์ฟเวอร์และยังคงเซสชันใน localStorageเพื่อให้คุณสามารถเข้าถึงผู้ใช้โดยใช้ {@link #current}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.