Перевірте, чи доступний localStorage


83

Я знаю, що було багато запитань щодо перевірки, localStorageале що, якщо хтось вручну вимкне її у своєму браузері? Ось код, який я використовую для перевірки:

localStorage.setItem('mod', 'mod');
if (localStorage.getItem('mod') != null){
  alert ('yes');
  localStorage.removeItem('mod');
} else {
  alert ('no');
}

Проста функція, і вона працює. Але якщо я заходжу в свої налаштування Chrome і вибираю опцію «Не зберігати дані» (я не пам’ятаю, як саме це називається), при спробі запустити цю функцію я не отримую нічого, крім Uncaught Error: SecurityError: DOM Exception 18. То чи є спосіб перевірити, чи у людини це повністю вимкнено?

ОНОВЛЕННЯ: Це друга функція, яку я спробував, і я все ще не отримую відповіді (попередження).

try {
  localStorage.setItem('name', 'Hello World!');
} catch (e) {
  if (e == QUOTA_EXCEEDED_ERR) {
   alert('Quota exceeded!');
  }
}

досі не надає жодного способу перевірити, працює це чи ні ...
user2025469

6
Ть-у-у-у. Якщо він видає виняток, ви знаєте, що це не працює
PeeHaa,


2
Можливий дублікат Check for HTML 5 localStorage
BuZZ-dEE 02.11.17

Відповіді:


133

Використовуйте modernizrпідхід '(можливо, ви хочете змінити ім'я моєї функції на щось краще):

function lsTest(){
    var test = 'test';
    try {
        localStorage.setItem(test, test);
        localStorage.removeItem(test);
        return true;
    } catch(e) {
        return false;
    }
}

if(lsTest() === true){
    // available
}else{
    // unavailable
}

Це не настільки стисло, як інші методи, але це тому, що воно розроблене для максимізації сумісності.

Першоджерело: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js

Робочий приклад: http://jsfiddle.net/6sm54/2/


1
Ей Джо, я отримую цю помилку під час запуску вашої функції (LS увімкнено або вимкнено) "Uncaught SyntaxError: Illegal return statement"
user2025469

1
@ user2025469 Цей код був призначений для використання як функції.
Кірусе

1
Вибачте, я повинен був про це згадати. Я оновив свою відповідь і додав демонстраційну версію, щоб ви бачили, що вона працює належним чином.
Джо

1
Джо, це саме те, що я шукав. Коли я включаю LS, він попереджає про недоступність. Це лише основна функція javascript, чи мені потрібно включити модернізар JS до свого сценарію>
user2025469

8
ОСТОРОЖНО! Цей підхід Modernizr поверне значення false, якщо буде досягнуто квоту localStorage. Якщо у вас є функції, що стосуються очищення localStorage, вам слід відредагувати оператор catch, щоб запустити відповідні дії очищення, якщо ім'я винятку e.name ==== 'QUOTA_EXCEEDED_ERR'(Chrome) або 'NS_ERROR_DOM_QUOTA_REACHED'(Firefox / Safari) або якщо localStorage.remainingSpace === 0в IE.
KrisWebDev

25

Я б перевірив, що localStorageвизначено до будь-якої дії, яка від цього залежить:

if (typeof localStorage !== 'undefined') {
    var x = localStorage.getItem('mod');
} else {
    // localStorage not defined
}

ОНОВЛЕННЯ:

Якщо вам потрібно підтвердити, що функція є і вона також не вимкнена, вам доведеться застосувати більш безпечний підхід. Щоб бути в повній безпеці:

if (typeof localStorage !== 'undefined') {
    try {
        localStorage.setItem('feature_test', 'yes');
        if (localStorage.getItem('feature_test') === 'yes') {
            localStorage.removeItem('feature_test');
            // localStorage is enabled
        } else {
            // localStorage is disabled
        }
    } catch(e) {
        // localStorage is disabled
    }
} else {
    // localStorage is not available
}

1
За даних обставин це лише функція, яка не дозволить іншим браузерам помилятися ... тому це насправді не відповідає на питання. Якщо його вимкнено, його localStorageвсе ще визначають у window.
Кірусе

1
Ви все ще отримуєте помилку DOM ... Я просто не можу повірити, що немає можливості перевірити, чи вона повністю вимкнена ...
user2025469

2
Це не безпечний підхід для Chrome та Opera ... ймовірно, не Safari, оскільки localStorageвін повністю недоступний, і буде вилучено виняток.
Shikkediel

Вам не потрібні всі ці elses ... Потрібна лише одна спроба зловити. Я бачу, ви перевіряєте, чи результат насправді є 'yes', але я не маю жодного випадку, коли це насправді потрібно.
Stijn de Witt

13

Місцеве сховище, що виявляє функції, досить складно. Вам потрібно насправді дотягнутися до цього. Причиною цього є те, що Safari вирішив запропонувати функціональний localStorageоб'єкт у приватному режимі, але з квотумом, встановленим на нуль . Це означає, що, хоча всі прості функції виявлення пройдуть, будь-які дзвінки до них localStorage.setItemвикличуть виняток.

Запис мережі розробників Mozilla в API веб-сховища має спеціальний розділ про функції виявлення локального сховища . Ось метод, рекомендований на цій сторінці:

function storageAvailable(type) {
    try {
        var storage = window[type],
            x = '__storage_test__';
        storage.setItem(x, x);
        storage.removeItem(x);
        return true;
    }
    catch(e) {
        return false;
    }
}

І ось як би ви це використали:

if (storageAvailable('localStorage')) {
    // Yippee! We can use localStorage awesomeness
}
else {
    // Too bad, no localStorage for us
}

Якщо ви використовуєте NPM, ви можете скористатися доступним сховищем

npm install -S storage-available

то використовуйте функцію так:

if (require('storage-available')('localStorage')) {
    // Yippee! We can use localStorage awesomeness
}

Застереження : Я як автор розділу документації щодо MDN та пакета NPM.


6

MDN оновив функцію виявлення пам’яті. У 2018 році це надійніше:

function storageAvailable() {
    try {
        var storage = window['localStorage'],
            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;
    }
}

Браузери, які підтримують localStorage, матимуть властивість для віконного об’єкта з ім’ям localStorage. Однак з різних причин лише твердження про наявність власності може спричинити винятки. Якщо він існує, це все ще не гарантує, що localStorage насправді доступний, оскільки різні браузери пропонують налаштування, які вимикають localStorage. Отже, браузер може підтримувати localStorage, але не робити його доступним для сценаріїв на сторінці. Одним із прикладів цього є Safari, який в режимі приватного перегляду дає нам порожній об’єкт localStorage з квотою нуля, фактично роблячи його непридатним для використання. Однак ми все одно можемо отримати законну QuotaExceededError, що означає лише те, що ми використали весь доступний простір для зберігання, але сховище фактично доступне. Наша функція виявлення особливостей повинна враховувати ці сценарії.

Дивіться тут коротку історію виявлення функцій localStorage .


Це не така поведінка, яку я спостерігаю в Safari з iOS 12.1. Я можу встановлювати речі та отримувати їх - вони просто не зберігаються після того, як я закрию цю вкладку. Навіть якщо я відвідаю інший веб-сайт на тій же вкладці і повернусь, збережені дані все ще є. Тож не впевнений, скільки років цьому коментарю.
Simon_Weaver

Очевидно, це була помилка, яка з тих пір була виправлена ​​- stackoverflow.com/questions/14555347/… . Потрібно припустити, що якщо ваші користувачі перебувають у приватному режимі, вони очікують втратити "сеанс", коли вони підуть та повернуться.
Simon_Weaver

This isn't the exact behavior I'm seeing in Safari with iOS 12.1. I'm able to set things and retrieve them - they just don't persist after I close that tab. Так. На щастя, розробники WebKit стали розумними та змінили порушену поведінку. У старих версіях вони викидають квоти, що перевищують помилки та будь-які спроби писати в localStorage, коли перебувають у приватному режимі. Це несподівано і спричинило багато проблем для розробників. У пізніших версіях вони змінили його відповідно до поведінки інших браузерів та файлів cookie: він буде працювати, але лише до тих пір, поки браузер залишається відкритим.
Stijn de Witt

Я не отримую жодної помилки під час спроби писати чи читати з локальної пам’яті під час використання приватного режиму Safari на мобільному. Safari просто нічого не зробить і мовчки провалиться.
Десь

1

За допомогою цієї функції ви можете перевірити, чи доступне місцеве зберігання чи ні, і ви тримаєте під контролем можливі винятки.

function isLocalStorageAvailable() {

    try {
        var valueToStore = 'test';
        var mykey = 'key';
        localStorage.setItem(mykey, valueToStore);
        var recoveredValue = localStorage.getItem(mykey);
        localStorage.removeItem(mykey);

        return recoveredValue === valueToStore;
    } catch(e) {
        return false;
    }
}

-1

Модифікація відповіді Джо для додавання геттера полегшує використання. Нижче ви просто говорите:if(ls)...

Object.defineProperty(this, "ls", {
  get: function () { 
    var test = 'test';
    try {
      localStorage.setItem(test, test);
      localStorage.removeItem(test);
      return true;
    } catch(e) {
      return false;
    }
  }
});

Чому голос проти? Це працює, і друкувати lsкраще, ніж друкувати lsTest() === true. ...?
Ронні Ройстон,

Вона не працює. Ви присвоюєте об'єкт ls... як такому if (ls)завжди оцінюватиметься true. Просто перевірте це, змінивши getметод читання, get: function(){return false}і ви побачите. Крім того, друкувати lsне краще .... Цей тест не буде занадто часто у вашому коді (якщо ви пишете його розумно), то навіщо забруднювати (глобальний) обсяг дуже короткою змінною?
Stijn de Witt

Ваше право. Мені доведеться це виправити ... Дякую!
Ронні Ройстон,

@StijndeWitt це працює зараз. Дякуємо за ваш відгук ... Що стосується забруднення глобального масштабу, я бачу вашу думку, але я думаю, що це така думка. Хтось може виявити, що друкувати if(ls){...варто.
Ронні Ройстон,

-2

Ось проста перевірка:

if(typeof localStorage === 'undefined'){


5
Тип localStorageповертається object, навіть якщо він вимкнений у Firefox або IE. У Chrome і Opera typeofвидає виняток і ламає весь сценарій, коли користувач вимикає його ...
Shikkediel

А в Safari в режимі приватного перегляду ви отримуєте робочий localStorageоб’єкт, що має нульову квоту, і, таким чином, виникає виняток, коли ви намагаєтесь написати на нього. Ось чому функція локального зберігання, що виявляє код, тепер завжди намагається написати елемент.
Stijn de Witt

-3

Використовуйте це, щоб перевірити, чи встановлено localStorage. Це допоможе вам отримати статус Localstorage.

    if( window.localStorage.fullName !== undefined){

           //action
   }else{
          }

4
Вам не потрібно чекати, поки документ буде завантажений, щоб отримати доступ до localStorage (тому $()це безглуздо). Важливіше те, що цей код видасть помилку, якщо localStorage буде недоступний.
1j01

Насправді, документи Mozilla стверджують, що вони localStorageмають синхронний характер, тому можуть блокувати візуалізацію основного документа. Тому чекати, поки він буде готовий, було б хорошим підходом.
Шиккедіель

Що вони мають на увазі під localStorageсинхронністю, це те, що localStorage.getItem('someKey')фактично негайно повертає товар. Він не приймає функції зворотного виклику або не повертає a Promise, він просто повертає дані відразу. Порівняйте, наприклад, var result = fetch('https://example.com/data.json')... що повертає a Promise, що робить його асинхронним. Вам потрібно буде викликати thenметод, щоб отримати дані (це відбудеться лише під час наступного галочки):result.then(function(data){ /* only here do we get the data */ })
Stijn de Witt

Мова йде про те, що синхронні виклики блокують візуалізацію, перериваючи подальший розбір сторінки. Поведінка зворотного дзвінка тут досить неактуальна.
Шиккедіель
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.