html5 localStorage เกิดข้อผิดพลาดกับ Safari:“ QUOTA_EXCEEDED_ERR: DOM Exception 22: มีความพยายามที่จะเพิ่มบางสิ่งบางอย่างลงในพื้นที่เก็บข้อมูลที่เกินโควต้า”


133

เว็บแอปของฉันมีข้อผิดพลาดจาวาสคริปต์ในการเรียกดูแบบส่วนตัวของ iOS Safari:

JavaScript: ข้อผิดพลาด

ไม่ได้กำหนด

QUOTA_EXCEEDED_ERR: DOM Exception 22: มีความพยายามที่จะเพิ่มบางสิ่งลงในที่เก็บข้อมูล ...

รหัสของฉัน:

localStorage.setItem('test',1)

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

4
สวัสดีครับผมช่วยรักษา safaridriver ปัญหานี้เป็นข้อบกพร่องที่มีมายาวนานใน WebKit ที่เพิ่งได้รับการแก้ไข ที่เก็บข้อมูลในเครื่องและที่เก็บเซสชันใช้งานได้ใน Safari 10.1 และใหม่กว่า การแก้ไขนี้มีผลกับโหมด Private Browsing ปกติและโหมด Automation (ใช้โดย WebDriver)
Brian Burg

คำตอบ:


184

เห็นได้ชัดว่านี่คือการออกแบบ เมื่อ 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;
    }
}

1
สิ่งนี้ไม่จำเป็นต้องเกิดจากโหมดไม่ระบุตัวตน ... แม้ว่าฉันเดาว่า OP ไม่ต้องการจัดเก็บข้อมูลหลายเมกะไบต์)
Christoph

6
ดูส่วนสำคัญนี้ที่แสดงประวัติโดยย่อของการตรวจจับที่เก็บข้อมูลในเครื่องโดย Paul Irish
Mottie

4
ดังนั้นในกรณีที่ localStorage ไม่ทำงานใน Safari การจัดเก็บทุกอย่างในคุกกี้เป็นตัวเลือกที่ดีที่สุดต่อไปหรือไม่?
Will Hitchcock

5
คล้ายกับตัวอย่างเช่นพอลไอริชผมขอแนะนำให้เปลี่ยนไปreturn localStorageName in win && win[localStorageName]; return trueจากนั้นคุณจะมีฟังก์ชันที่ส่งคืนจริงหรือเท็จอย่างปลอดภัยขึ้นอยู่กับความพร้อมใช้งานของ localStorage ตัวอย่าง:if (isLocalStorageNameSupported()) { /* You can use localStorage.setItem */ } else { /* you can't use localStorage.setItem */ }
DrewT

1
ตรวจสอบแล้วว่าปัญหาไม่ได้เกิดเฉพาะกับหน้าต่างส่วนตัวเท่านั้น แต่ยังมีหน้าต่างซาฟารีปกติด้วย
codemirror

38

การแก้ไขที่โพสต์ไว้ในลิงก์ด้านบนไม่ได้ผลสำหรับฉัน สิ่งนี้ทำ:

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


20
มีเหตุผลใดที่คุณ (และ @KingKongFrog) ใช้ window.sessionStorage เพื่อตรวจสอบว่าคุณสามารถเขียนลงใน localStorage ได้หรือไม่หรือเราอยู่ในวงจรพิมพ์ผิดคัดลอกวางแปลก ๆ ?
Yetti

@ Yetti หากคุณสังเกตเห็นการพิมพ์ผิดทำไมคุณไม่แก้ไขในการแก้ไขหรือในความคิดเห็นของคุณ เท่าที่ฉันรู้ว่าwindow.sessionStorageถูกต้อง มันใช้งานได้อย่างแน่นอนในรหัสของฉัน โปรดชี้ให้เห็นการแก้ไขปัญหาที่คุณควรทราบ
Novocaine

7
@Novocaine ความคิดเห็นของฉันชี้ให้เห็นว่าพวกเขากำลังใช้ sessionStorage ในฟังก์ชันที่มีอยู่เพื่อตรวจสอบการสนับสนุน localStorage ใช่มันน่าจะยังใช้งานได้ แต่ตามที่เขียนไว้ชื่อฟังก์ชันทำให้เข้าใจผิดสำหรับสิ่งที่กำลังทดสอบจริง ฉันเลือกที่จะแสดงความคิดเห็นแทนที่จะแก้ไขเพราะฉันคิดว่าตัวเองขาดอะไรไปและหวังว่าจะได้เรียนรู้จากคนเหล่านี้ น่าเสียดายที่พวกเขายังไม่ได้ตอบกลับหรือทำการแก้ไขดังนั้นเราจึงอยู่ที่นี่
Yetti

3
@Yetti ขอบคุณที่ชี้แจง ฉันเห็นสิ่งที่คุณกำลังทำอยู่ตอนนี้ ; -]
Novocaine

2
@DawsonToth ไม่มีมันเป็นเพราะผมเรียกว่าฟังก์ชั่นและได้รับการตรวจสอบisLocalStorageNameSupported window.sessionStorageผลลัพธ์สุดท้ายเหมือนกัน แต่สับสนเล็กน้อย คำตอบถูกแก้ไขเพื่อชี้แจง
cyberwombat

25

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

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

อย่างไรก็ตามหากคุณต้องการ 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.');
    }
}

11

ในบริบทของฉันเพิ่งพัฒนาสิ่งที่เป็นนามธรรมของชั้นเรียน เมื่อใบสมัครของฉันมีการเปิดตัวผมตรวจสอบว่า 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();

2
ขอบคุณปิแอร์คำตอบของคุณเป็นแรงบันดาลใจให้ฉัน ฉันสิ้นสุดขึ้นบรรจุภัณฑ์ทั้งหมดในโมดูลที่ดีเรียกว่าmemorystorage โอเพ่นซอร์สแน่นอน สำหรับคนอื่น ๆ ที่มีปัญหาเดียวกันลองดูวิธีนี้อาจช่วยคุณได้
Stijn de Witt

ฮ่า. ฉันทำสิ่งเดียวกัน (อิสระ) ยังคงใช้ตัวแปร localStorage (อย่างน้อยที่สุดใน Safari คุณไม่สามารถเขียนทับตัวแปร localStorage ได้ (เป็น 'อ่านอย่างเดียว') แต่คุณสามารถกำหนด setItem / removeItem / getItem ใหม่ได้)
Ruben Martinez Jr.

@StijndeWitt ฉันจะเข้าถึงค่าที่เก็บข้อมูลของฉันในหน้าอื่น ๆ ได้อย่างไร ตัวอย่างเช่นฉันมีสิ่งนี้ใน helper.php var store = MemoryStorage ('my-app'); store.setItem ('myString', 'สวัสดี MemoryStorage!'); ฉันต้องการเข้าถึงค่าของ myString ใน Lecture.php ฉันพยายามเริ่มการจัดเก็บหน่วยความจำในเพจ แต่ยังคงแสดงวัตถุว่างเปล่า
user1149244

@ user1149244 Memorystorage อยู่ในเครื่องของเพจ มันจำลอง Web Storage API และสามารถใช้เป็นทางเลือกเมื่อ localStorage และ sessionStorage ไม่พร้อมใช้งาน อย่างไรก็ตามข้อมูลจะถูกเก็บไว้ในหน่วยความจำเพจเท่านั้น (จึงเป็นชื่อ) หากคุณต้องการเก็บรักษาข้อมูลในหน้าต่างๆคุกกี้อาจช่วยคุณได้ แต่มีจำนวนข้อมูลที่ จำกัด มากที่สามารถจัดเก็บได้ นอกเหนือจากนั้นมีไม่มากที่สามารถทำได้
Stijn de Witt

2
@ user1149244 นี่ไม่ควรเก็บค่าในเบราว์เซอร์ใช่ไหม ไม่มันไม่ได้ มี 3 วิธีในการจัดเก็บสิ่งของฝั่งไคลเอ็นต์จากการรีเฟรชหน้าหนึ่งไปยังอีกหน้าหนึ่ง ได้แก่ คุกกี้, sessionStorage / localStorage และ IndexedDB สองคนสุดท้ายค่อนข้างใหม่ sessionStorage และ localStorage ได้รับการสนับสนุนอย่างกว้างขวางเพื่อให้คุณสามารถใช้งานได้ทุกที่ ยกเว้นในโหมดการท่องเว็บแบบส่วนตัวซึ่งเป็นปัญหาเกี่ยวกับ โปรแกรมขัดข้องเนื่องจากไม่มีที่เก็บข้อมูล memorystorage มีเพียงทางเลือกสำรองที่ใช้งานได้ตลอดเวลาในเพจ แต่ไม่สามารถบันทึกข้อมูลได้จริง มันคือต้นขั้ว แต่ไม่มีข้อผิดพลาด
Stijn de Witt

5

ดูเหมือนว่า Safari 11 จะเปลี่ยนพฤติกรรมและตอนนี้ที่เก็บข้อมูลในเครื่องทำงานในหน้าต่างเบราว์เซอร์ส่วนตัว ไชโย!

เว็บแอปของเราที่เคยล้มเหลวในการท่องเว็บแบบส่วนตัวของ Safari ตอนนี้ทำงานได้อย่างไม่มีที่ติ มันทำงานได้ดีเสมอในโหมดการท่องเว็บส่วนตัวของ Chrome ซึ่งอนุญาตให้เขียนลงในพื้นที่จัดเก็บข้อมูลในเครื่องได้เสมอ

เอกสารนี้อยู่ในบันทึกประจำรุ่น Safari Technology Previewของ Apple และบันทึกประจำรุ่น WebKitสำหรับรุ่นที่ 29 ซึ่งเป็นในเดือนพฤษภาคม 2017

โดยเฉพาะ:

  • แก้ไข QuotaExceededError เมื่อบันทึกลงใน localStorage ในโหมดการท่องเว็บส่วนตัวหรือเซสชัน WebDriver - r215315

4

หากต้องการขยายคำตอบของผู้อื่นนี่คือโซลูชันขนาดกะทัดรัดที่ไม่เปิดเผย / เพิ่มตัวแปรใหม่ ๆ ไม่ครอบคลุมทุกฐาน แต่ควรเหมาะกับคนส่วนใหญ่ที่ต้องการให้แอปหน้าเดียวใช้งานได้ (แม้จะไม่มีข้อมูลคงอยู่หลังจากโหลดซ้ำ)

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

3

ฉันมีปัญหาเดียวกันกับการใช้ Ionic framework (Angular + Cordova) ฉันรู้ว่าสิ่งนี้ไม่สามารถแก้ปัญหาได้ แต่เป็นรหัสสำหรับ Angular Apps ตามคำตอบด้านบน คุณจะมีวิธีแก้ปัญหาชั่วคราวสำหรับ localStorage บน Safari เวอร์ชัน iOS

นี่คือรหัส:

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

สนุกกับการเขียนโค้ดของคุณ!


1
แม้ว่านี่จะไม่ตอบคำถาม แต่นี่เป็นสิ่งแรกที่เกิดขึ้นเมื่อฉัน googled ปัญหา ขั้นตอนต่อไปคือการค้นหาวิธีแก้ปัญหาสำหรับ Angular แต่ต้องขอบคุณความคิดเห็นนี้ฉันไม่ต้องไปที่อื่น ดังนั้นอาจไม่ได้ตอบคำถามโดยตรง แต่เหมาะสำหรับฉันและน่าจะเป็นไปได้สำหรับคนอื่น ๆ !
Leonard

2

นี่คือทางออกสำหรับ AngularJS ใช้IIFEและใช้ประโยชน์จากความจริงที่ว่าบริการ singletons

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

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

1

ฉันเพิ่งสร้างrepoนี้เพื่อให้บริการsessionStorageและlocalStorageคุณลักษณะสำหรับเบราว์เซอร์ที่ไม่รองรับหรือปิดใช้งาน

เบราว์เซอร์ที่รองรับ

  • IE5 +
  • Chrome ทุกเวอร์ชัน
  • Mozilla ทุกเวอร์ชัน
  • ยานเดกซ์ทุกรุ่น

มันทำงานอย่างไร

ตรวจพบคุณสมบัติที่มีประเภทการจัดเก็บ

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

ชุดStorageService.localStorageไปwindow.localStorageถ้ามันได้รับการสนับสนุนหรือสร้างจัดเก็บคุกกี้ ชุดStorageService.sessionStorageไปwindow.sessionStorageถ้ามันได้รับการสนับสนุนหรือสร้างในการจัดเก็บหน่วยความจำสำหรับสปาที่เก็บคุกกี้ sesion ให้บริการสำหรับผู้ที่ไม่ใช่สปา


1
ขอบคุณห้องสมุดของคุณช่วยได้มาก!
Mathieu

1

นี่คือเวอร์ชันบริการ Angular2 + สำหรับทางเลือกในการจัดเก็บหน่วยความจำคุณสามารถฉีดเข้าไปในส่วนประกอบของคุณตามคำตอบของ Pierre Le Roux

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

อย่าใช้หากไม่รองรับและตรวจสอบการสนับสนุนเพียงแค่เรียกใช้ฟังก์ชันนี้

การแบ่งปันใน Es6 แบบเต็มอ่านและเขียน localStorage ตัวอย่างพร้อมการตรวจสอบการสนับสนุน

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

เพื่อให้แน่ใจว่าคีย์ของคุณได้รับการตั้งค่าและเรียกใช้อย่างถูกต้องในทุกเบราว์เซอร์


0

ฉันได้สร้างโปรแกรมแก้ไขสำหรับปัญหานี้แล้ว ฉันกำลังตรวจสอบว่าเบราว์เซอร์รองรับ localStorage หรือ sessionStorage หรือไม่ ถ้าไม่เช่นนั้นเครื่องมือจัดเก็บข้อมูลจะเป็น Cookie แต่ด้านลบคือ Cookie มีหน่วยความจำที่เล็กมาก :(

function StorageEngine(engine) {
    this.engine = engine || 'localStorage';

    if(!this.checkStorageApi(this.engine)) {
        // Default engine would be alway cooke
        // Safari private browsing issue with localStorage / sessionStorage
        this.engine = 'cookie';
    }
}

StorageEngine.prototype.checkStorageApi = function(name) {
    if(!window[name]) return false;
    try {
        var tempKey = '__temp_'+Date.now();
        window[name].setItem(tempKey, 'hi')
        window[name].removeItem(tempKey);
        return true;
    } catch(e) {
        return false;
    }
}

StorageEngine.prototype.getItem = function(key) {
    if(['sessionStorage', 'localStorage'].includes(this.engine)) {
        return window[this.engine].getItem(key);
    } else if('cookie') {
        var name = key+"=";
        var allCookie = decodeURIComponent(document.cookie).split(';');
        var cval = [];
        for(var i=0; i < allCookie.length; i++) {
            if (allCookie[i].trim().indexOf(name) == 0) {
                cval = allCookie[i].trim().split("=");
            }   
        }
        return (cval.length > 0) ? cval[1] : null;
    }
    return null;
}

StorageEngine.prototype.setItem = function(key, val, exdays) {
    if(['sessionStorage', 'localStorage'].includes(this.engine)) {
        window[this.engine].setItem(key, val);
    } else if('cookie') {
        var d = new Date();
        var exdays = exdays || 1;
        d.setTime(d.getTime() + (exdays*24*36E5));
        var expires = "expires="+ d.toUTCString();
        document.cookie = key + "=" + val + ";" + expires + ";path=/";
    }
    return true;
}


// ------------------------
var StorageEngine = new StorageEngine(); // new StorageEngine('localStorage');
// If your current browser (IOS safary or any) does not support localStorage/sessionStorage, then the default engine will be "cookie"

StorageEngine.setItem('keyName', 'val')

var expireDay = 1; // for cookie only
StorageEngine.setItem('keyName', 'val', expireDay)
StorageEngine.getItem('keyName')

0

คำตอบที่ยอมรับดูเหมือนจะไม่เพียงพอในหลาย ๆ สถานการณ์

เพื่อตรวจสอบว่าlocalStorageหรือsessionStorageได้รับการสนับสนุนผมใช้ข้อมูลต่อไปนี้จากMDN

function storageAvailable(type) {
    var storage;
    try {
        storage = window[type];
        var x = '__storage_test__';
        storage.setItem(x, x);
        storage.removeItem(x);
        return true;
    }
    catch(e) {
        return e instanceof DOMException && (
            // everything except Firefox
            e.code === 22 ||
            // Firefox
            e.code === 1014 ||
            // test name field too, because code might not be present
            // everything except Firefox
            e.name === 'QuotaExceededError' ||
            // Firefox
            e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
            // acknowledge QuotaExceededError only if there's something already stored
            (storage && storage.length !== 0);
    }
}

ใช้ตัวอย่างข้อมูลในลักษณะนี้และใช้ทางเลือกอื่นเช่นการใช้คุกกี้:

if (storageAvailable('localStorage')) {
  // Yippee! We can use localStorage awesomeness
}
else {
  // Too bad, no localStorage for us
  document.cookie = key + "=" + encodeURIComponent(value) + expires + "; path=/";
}

ฉันได้สร้างแพ็กเกจfallbackstorageซึ่งใช้ข้อมูลโค้ดนี้เพื่อตรวจสอบความพร้อมใช้งานของพื้นที่เก็บข้อมูลและทางเลือกที่จะใช้ MemoryStorage ด้วยตนเอง

import {getSafeStorage} from 'fallbackstorage'

getSafeStorage().setItem('test', '1') // always work

-1
var mod = 'test';
      try {
        sessionStorage.setItem(mod, mod);
        sessionStorage.removeItem(mod);
        return true;
      } catch (e) {
        return false;
      }

1
บางทีคุณอาจต้องการเพิ่มคำอธิบายสองสามคำ?
bogl

-2

สคริปต์ต่อไปนี้ช่วยแก้ปัญหาของฉัน:

// Fake localStorage implementation. 
// Mimics localStorage, including events. 
// It will work just like localStorage, except for the persistant storage part. 

var fakeLocalStorage = function() {
  var fakeLocalStorage = {};
  var storage; 

  // If Storage exists we modify it to write to our fakeLocalStorage object instead. 
  // If Storage does not exist we create an empty object. 
  if (window.Storage && window.localStorage) {
    storage = window.Storage.prototype; 
  } else {
    // We don't bother implementing a fake Storage object
    window.localStorage = {}; 
    storage = window.localStorage; 
  }

  // For older IE
  if (!window.location.origin) {
    window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
  }

  var dispatchStorageEvent = function(key, newValue) {
    var oldValue = (key == null) ? null : storage.getItem(key); // `==` to match both null and undefined
    var url = location.href.substr(location.origin.length);
    var storageEvent = document.createEvent('StorageEvent'); // For IE, http://stackoverflow.com/a/25514935/1214183

    storageEvent.initStorageEvent('storage', false, false, key, oldValue, newValue, url, null);
    window.dispatchEvent(storageEvent);
  };

  storage.key = function(i) {
    var key = Object.keys(fakeLocalStorage)[i];
    return typeof key === 'string' ? key : null;
  };

  storage.getItem = function(key) {
    return typeof fakeLocalStorage[key] === 'string' ? fakeLocalStorage[key] : null;
  };

  storage.setItem = function(key, value) {
    dispatchStorageEvent(key, value);
    fakeLocalStorage[key] = String(value);
  };

  storage.removeItem = function(key) {
    dispatchStorageEvent(key, null);
    delete fakeLocalStorage[key];
  };

  storage.clear = function() {
    dispatchStorageEvent(null, null);
    fakeLocalStorage = {};
  };
};

// Example of how to use it
if (typeof window.localStorage === 'object') {
  // Safari will throw a fit if we try to use localStorage.setItem in private browsing mode. 
  try {
    localStorage.setItem('localStorageTest', 1);
    localStorage.removeItem('localStorageTest');
  } catch (e) {
    fakeLocalStorage();
  }
} else {
  // Use fake localStorage for any browser that does not support it.
  fakeLocalStorage();
}

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

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