检查localStorage是否可用


79

我知道有关检查的问题很多,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 2013年

6
嗯。如果它引发异常,您就知道它不起作用
PeeHaa


Answers:


129

使用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 2013年

1
@ user2025469该代码旨在用作功能。
Kiruse

1
抱歉,我应该提到这一点。我已经更新了答案并添加了一个演示,以便您可以看到它正常工作。

1
乔,那正是我一直在寻找的东西。当我打开LS时,它会发出警报。这是基本的javascript函数还是我需要在脚本中包含modernizr JS>
user2025469 2013年

7
谨防!如果达到localStorage配额,则此Modernizr方法将返回false。如果您具有处理localStorage清理的功能,则应编辑catch语句,以在异常名称e.name ==== 'QUOTA_EXCEEDED_ERR'(Chrome)或'NS_ERROR_DOM_QUOTA_REACHED'(Firefox / Safari)或localStorage.remainingSpace === 0IE中启动适当的清理操作。
KrisWebDev

24

我会先检查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
Kiruse 2013年

1
您仍然会收到DOM错误...我简直不敢相信没有办法检查它是否已完全关闭...
user2025469 2013年

2
对于Chrome和Opera,这不是一种安全的方法... Safari也可能不是,因为localStorage完全无法访问,并且会引发异常。
Shikkediel

您不需要所有这些else……只需一个try catch就可以了。我看到您正在测试结果实际上是'yes',但是我绝对没有用例是实际必要的。
Stijn de Witt

11

功能检测本地存储非常棘手。您实际上需要深入了解它。原因是Safari选择localStorage在私有模式下提供功能对象,但其quotum设置为零。这意味着,尽管所有简单的功能检测都将通过,但是任何对的调用都localStorage.setItem将引发异常。

Web Storage API上的Mozilla的Developer Network条目有一个专门的部分介绍功能检测本地存储。这是该页面上推荐的方法:

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软件包的文档部分均由我编写。


5

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简要历史记录


这不是我在iOS 12.1的Safari中看到的确切行为。我能够设置并检索它们-在关闭该选项卡后它们不会持久存在。即使我访问了同一标签中的另一个网站,然后回来,我保存的数据仍然在那里。因此,不确定此评论的年龄。
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只会无所事事,并且会无声无息地失败。
SomewhereDave

0

使用此功能,您可以检查本地存储是否可用,并且可以控制可能的异常。

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

修改Joe的答案以添加吸气剂使其更易于使用。在下面,您只需说: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 2016年

在Safari的“私人浏览”模式下,您将获得一个工作localStorage对象,该工作对象的配额为零,因此在您尝试对其进行写入时都会引发异常。这就是为什么本地存储功能检测代码现在始终尝试写入项目的原因。
Stijn de Witt

-3

使用此命令检查是否设置了localStorage。它可以帮助您获取Localstorage的状态。

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

           //action
   }else{
          }

4
您不需要等待文档加载就可以访问localStorage(因此$()毫无意义)。更重要的是,如果localStorage不可用,则此代码将引发错误。
1j01 2014年

实际上,Mozilla文档声称localStorage其本质上是同步的,因此它可以阻止主文档的呈现。因此,等待它准备就绪将是一个好方法。
Shikkediel

他们说的localStorage是同步的意思是localStorage.getItem('someKey')实际上立即返回了该项目。它不接受回调函数或不返回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

这是因为同步调用会阻止渲染,从而中断页面的进一步解析。此处的回调行为是无关紧要的。
Shikkediel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.