html5 localStorage lỗi với Safari:


133

Ứng dụng web của tôi có lỗi javascript trong trình duyệt riêng tư của ios safari:

JavaScript: lỗi

chưa xác định

QUOTA_EXCEEDED_ERR: DOM Ngoại lệ 22: Một nỗ lực đã được thực hiện để thêm một cái gì đó vào bộ lưu trữ ...

mã của tôi:

localStorage.setItem('test',1)

Sử dụng một tính năng phát hiện các bài kiểm tra cho vấn đề cụ thể này . Nếu lưu trữ là không có sẵn, hãy xem xét shimming localStorage với memoryStorage . từ chối trách nhiệm: Tôi là tác giả của các gói được liên kết
Stijn de Witt

4
Xin chào mọi người, tôi giúp duy trì safaridriver. Sự cố này là một lỗi lâu đời trong WebKit đã được sửa gần đây. Lưu trữ cục bộ và lưu trữ phiên hiện hoạt động trong Safari 10.1 trở lên. Khắc phục sự cố này ảnh hưởng đến chế độ Duyệt web riêng tư và chế độ Tự động hóa thông thường (được sử dụng bởi WebDriver).
Brian Burg

Câu trả lời:


183

Rõ ràng đây là do thiết kế. Khi Safari (OS X hoặc iOS) ở chế độ duyệt web riêng tư, nó xuất hiện như thể localStoragecó sẵn, nhưng cố gắng gọi setItemmột ngoại lệ.

store.js line 73
"QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota."

Điều xảy ra là đối tượng cửa sổ vẫn hiển thị localStoragetrong không gian tên toàn cục, nhưng khi bạn gọi setItem, ngoại lệ này được đưa ra. Bất kỳ cuộc gọi đến removeItemđược bỏ qua.

Tôi tin rằng cách khắc phục đơn giản nhất (mặc dù tôi chưa thử nghiệm trình duyệt chéo này) sẽ là thay đổi chức năng isLocalStorageNameSupported()để kiểm tra rằng bạn cũng có thể đặt một số giá trị.

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
Điều này không nhất thiết phải do chế độ ẩn danh ... mặc dù tôi đoán OP không muốn lưu trữ vài megabyte dữ liệu;)
Christoph

5
Kiểm tra ý chính này cho thấy một lịch sử ngắn gọn về việc phát hiện lưu trữ địa phương của Paul Irish.
Mottie

4
Vậy trong trường hợp localStorage không hoạt động trong Safari, việc lưu trữ mọi thứ trong cookie là lựa chọn tốt nhất tiếp theo?
Will Hitchcock

5
Tương tự như ví dụ Paul Ailen, tôi đề nghị thay đổi return localStorageName in win && win[localStorageName];thành return true. Sau đó, bạn có một hàm an toàn trả về đúng hoặc sai tùy thuộc vào tính khả dụng của localStorage. Ví dụ:if (isLocalStorageNameSupported()) { /* You can use localStorage.setItem */ } else { /* you can't use localStorage.setItem */ }
DrewT

1
Xác minh rằng vấn đề không chỉ với cửa sổ riêng mà cả cửa sổ safari bình thường cũng có.
codemirror

38

Các sửa chữa được đăng trên liên kết trên không làm việc cho tôi. Điều này đã làm:

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

Bắt nguồn từ http://m.cg/post/13095478393/detect-private-browsing-mode-in-mobile-safari-on-ios5


20
Bất kỳ lý do cụ thể nào mà bạn (và @KingKongFrog) đang sử dụng window.sessionStorage để phát hiện xem bạn có thể viết thư cho localStorage hay chúng ta đang ở trong một chu kỳ đánh máy sao chép kỳ lạ?
Yetti

@Yetti nếu bạn nhận thấy một lỗi đánh máy, tại sao bạn không sửa nó trong một chỉnh sửa hoặc trong nhận xét của bạn? Theo như tôi biết window.sessionStoragelà đúng. Nó chắc chắn hoạt động trong mã của tôi. Hãy thực sự chỉ ra cách khắc phục vấn đề mà bạn dường như biết.
Novocaine

7
@Novocaine Nhận xét của tôi đã chỉ ra rằng họ đang sử dụng sessionStorage trong một chức năng tồn tại để kiểm tra hỗ trợ localStorage. Vâng, nó có thể sẽ vẫn hoạt động, nhưng, như đã viết, tên hàm gây hiểu nhầm cho những gì thực sự đang được thử nghiệm. Tôi đã chọn bình luận, thay vì chỉnh sửa, vì tôi nghĩ rằng tôi đang thiếu một cái gì đó và hy vọng học hỏi từ những người này. Thật không may, họ đã không trả lời hoặc thực hiện một sự điều chỉnh vì vậy chúng tôi đang ở đây.
Yetti

3
@Yetti Cảm ơn bạn đã làm rõ. Tôi thấy những gì bạn đang về về bây giờ. ; -]
Novocaine

2
@DawsonToth không phải vì tôi đã gọi hàm isLocalStorageNameSupportedvà đang kiểm tra window.sessionStorage. Kết quả cuối cùng giống nhau nhưng có một chút khó hiểu. Câu trả lời đã được chỉnh sửa để làm rõ.
cyberwombat

25

Như đã đề cập trong các câu trả lời khác, bạn sẽ luôn nhận được QuotaExceededError trong Chế độ trình duyệt riêng của Safari trên cả iOS và OS X khi localStorage.setItem (hoặc sessionStorage.setItem) được gọi.

Một giải pháp là thử / bắt hoặc kiểm tra Modernizr trong mỗi trường hợp sử dụng setItem.

Tuy nhiên, nếu bạn muốn một shim đơn giản là toàn cầu ngăn chặn lỗi này bị ném, để ngăn phần còn lại của JavaScript bị phá vỡ, bạn có thể sử dụng điều này:

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

Trong bối cảnh của tôi, chỉ cần phát triển một trừu tượng lớp. Khi ứng dụng của tôi được khởi chạy, tôi kiểm tra xem localStorage có hoạt động không bằng cách gọi getStorage () . Hàm này cũng trả về:

  • hoặc localStorage nếu localStorage đang hoạt động
  • hoặc triển khai lớp tùy chỉnh LocalStorageAlternative

Trong mã của tôi, tôi không bao giờ gọi localStorage trực tiếp. Tôi gọi cusSto var toàn cầu, tôi đã khởi tạo bằng cách gọi getStorage () .

Bằng cách này, nó hoạt động với trình duyệt riêng tư hoặc các phiên bản Safari cụ thể

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
Cảm ơn Pierre, câu trả lời của bạn đã truyền cảm hứng cho tôi. Tôi đã kết thúc việc đóng gói tất cả trong một mô-đun đẹp gọi là bộ nhớ . Nguồn mở của khóa học. Đối với những người khác có cùng vấn đề, hãy kiểm tra xem nó có thể giúp bạn không.
Stijn de Witt

Hà. Tôi đã làm điều tương tự (độc lập). Vẫn sử dụng biến localStorage mặc dù (trong Safari, ít nhất, bạn không thể ghi đè lên biến localStorage (đó là 'chỉ đọc'), nhưng bạn có thể gán lại setItem / removeItem / getItem).
Ruben Martinez Jr.

@StijndeWitt, làm cách nào tôi có thể truy cập các giá trị lưu trữ của mình trong các trang khác? Ví dụ: tôi có cái này trong helper.php var store = MemoryStorage ('my-app'); store.setItem ('myString', 'Xin chào MemoryStorage!'); Tôi muốn truy cập giá trị của myString trong speechure.php. Tôi đã thử khởi tạo bộ nhớ trong trang nhưng nó vẫn hiển thị một đối tượng trống.
dùng1149244

@ user1149244 Bộ nhớ lưu trữ cục bộ trên trang. Nó mô phỏng API lưu trữ web và như vậy có thể được sử dụng làm dự phòng khi localStorage và sessionStorage không khả dụng. Tuy nhiên, dữ liệu sẽ chỉ được giữ lại trong bộ nhớ trang (do đó là tên). Nếu bạn cần dữ liệu được giữ lại trên các trang, cookie có thể giúp bạn. Nhưng nó rất hạn chế về số lượng dữ liệu có thể được lưu trữ. Khác hơn là không có nhiều có thể được thực hiện.
Stijn de Witt

2
@ user1149244 Đây có phải là lưu trữ các giá trị trong trình duyệt không? Không, nó không thể. Có 3 cách để lưu trữ công cụ phía máy khách từ làm mới trang này sang trang khác: cookie, sessionStorage / localStorage và IndexedDB. Hai cuối cùng là tương đối mới. sessionStorage và localStorage được hỗ trợ rộng rãi để bạn có thể sử dụng nó cơ bản ở mọi nơi. ngoại trừ trong chế độ duyệt web riêng tư , đó là vấn đề này. Các chương trình bị hỏng vì không có bộ nhớ. bộ nhớ chỉ cung cấp một dự phòng luôn hoạt động trong khi trên trang, nhưng nó thực sự không thể lưu dữ liệu. Đó là một sơ khai. Nhưng không có lỗi.
Stijn de Witt

5

Có vẻ như Safari 11 thay đổi hành vi và hiện tại bộ nhớ cục bộ hoạt động trong cửa sổ trình duyệt riêng. Hoan hô!

Ứng dụng web của chúng tôi từng thất bại trong trình duyệt riêng tư Safari giờ đây hoạt động hoàn hảo. Nó luôn hoạt động tốt trong chế độ duyệt web riêng tư của Chrome, vốn luôn cho phép ghi vào bộ nhớ cục bộ.

Đây là tài liệu trong ghi chú phát hành Bản xem trước công nghệ Safari của Apple - và ghi chú phát hành WebKit - cho bản phát hành 29, vào tháng 5 năm 2017.

Đặc biệt:

  • Đã sửa lỗi QuotaExceededError khi lưu vào localStorage ở chế độ duyệt web riêng tư hoặc các phiên WebDriver - r215315

4

Để mở rộng câu trả lời của người khác, đây là một giải pháp nhỏ gọn không phơi bày / thêm bất kỳ biến mới nào. Nó không bao gồm tất cả các cơ sở, nhưng nó phù hợp với hầu hết những người chỉ muốn một ứng dụng trang duy trì hoạt động (mặc dù không có dữ liệu tồn tại sau khi tải lại).

(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

Tôi gặp vấn đề tương tự khi sử dụng khung Ionic (Angular + Cordova). Tôi biết điều này không giải quyết được vấn đề, nhưng đó là mã cho Ứng dụng Angular dựa trên các câu trả lời ở trên. Bạn sẽ có một giải pháp phù du cho localStorage trên phiên bản Safari của iOS.

Đây là mã:

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

Nguồn: https://gist.github.com/jorgecasar/61fda6590dc2bb17e871

Thưởng thức mã hóa của bạn!


1
Mặc dù điều này không trả lời câu hỏi, đây là điều đầu tiên xuất hiện khi tôi giải quyết vấn đề. Bước tiếp theo sẽ là tìm kiếm giải pháp cho Angular nhưng nhờ nhận xét này mà tôi không phải đi nơi khác. Vì vậy, có thể không trực tiếp trả lời câu hỏi nhưng rất tốt cho tôi và có khả năng cho những người khác!
Leonard

2

Đây là một giải pháp cho AngularJS sử dụng IIFE và thúc đẩy thực tế rằng các dịch vụ là singletons .

Điều này dẫn đến isLocalStorageAvailableviệc được đặt ngay lập tức khi dịch vụ được tiêm lần đầu tiên và tránh việc chạy kiểm tra một cách không cần thiết mỗi khi cần truy cập bộ nhớ cục bộ.

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

Tôi vừa tạo repo này để cung cấp sessionStoragelocalStoragecác tính năng cho các trình duyệt không được hỗ trợ hoặc bị vô hiệu hóa.

Các trình duyệt được hỗ trợ

  • IE5 +
  • Chrome tất cả các phiên bản
  • Mozilla tất cả các phiên bản
  • Yandex tất cả các phiên bản

Làm thế nào nó hoạt động

Nó phát hiện các tính năng với loại lưu trữ.

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

Đặt StorageService.localStoragethành window.localStoragenếu nó được hỗ trợ hoặc tạo bộ lưu trữ cookie. Đặt StorageService.sessionStoragethành window.sessionStoragenếu nó được hỗ trợ hoặc tạo bộ nhớ lưu trữ cho SPA, lưu trữ cookie với các tính năng Sesion cho không phải SPA.


1
Cảm ơn, thư viện của bạn đã giúp rất nhiều!
Mathieu

1

Đây là phiên bản dịch vụ Angular2 + để thay thế bộ nhớ lưu trữ, bạn chỉ có thể đưa vào các thành phần của mình, dựa trên câu trả lời của 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

Không sử dụng nó nếu không được hỗ trợ và để kiểm tra hỗ trợ chỉ cần gọi chức năng này

chia sẻ trong Es6 toàn bộ đọc và viết localStorage Ví dụ với kiểm tra hỗ trợ

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

Điều này sẽ đảm bảo các khóa của bạn được đặt và truy xuất đúng cách trên tất cả các trình duyệt.


0

Tôi đã tạo ra một bản vá cho vấn đề. Đơn giản là tôi đang kiểm tra xem trình duyệt có hỗ trợ localStorage hoặc sessionStorage hay không. Nếu không thì công cụ lưu trữ sẽ là Cookie. Nhưng mặt tiêu cực là Cookie có bộ nhớ lưu trữ rất nhỏ :(

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

Câu trả lời được chấp nhận dường như không đầy đủ trong một số tình huống.

Để kiểm tra xem có được hỗ trợ localStoragehay sessionStoragekhông, tôi sử dụng đoạn mã sau từ 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);
    }
}

Sử dụng đoạn mã như thế này và ví dụ, sử dụng cookie:

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

Tôi đã thực hiện gói dự phòng sử dụng đoạn mã này để kiểm tra tính khả dụng của bộ lưu trữ và dự phòng cho Bộ nhớ được triển khai thủ công.

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
Có lẽ bạn muốn thêm một vài lời giải thích?
bogl

-2

Kịch bản sau đây đã giải quyết vấn đề của tôi:

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

Nó kiểm tra nếu localStorage tồn tại và có thể được sử dụng và trong trường hợp tiêu cực, nó tạo ra một bộ lưu trữ cục bộ giả và sử dụng nó thay vì localStorage ban đầu. Xin vui lòng cho tôi biết nếu bạn cần thêm thông tin.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.