【问题标题】:Check if localStorage is available检查 localStorage 是否可用
【发布时间】:2013-05-01 21:55:51
【问题描述】:

我知道有很多关于检查 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!');
  }
}

【问题讨论】:

标签: javascript error-handling local-storage


【解决方案1】:

使用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/

【讨论】:

  • 嘿乔,我在运行你的函数时遇到这个错误(LS 开启或关闭)“Uncaught SyntaxError: Illegal return statement”
  • @user2025469 此代码旨在用作函数。
  • 对不起,我应该提到这一点。我已经更新了我的答案并添加了一个演示,以便您可以看到它正常工作。
  • 乔,这正是我一直在寻找的。当我打开 LS 时,它会提示不可用。这只是一个基本的javascript函数还是我需要在我的脚本中包含modernizr JS>
  • 当心!如果达到 localStorage 配额,此 Modernizr 方法将返回 false。如果您有处理 localStorage 清理的函数,您应该编辑 catch 语句以在异常名称 e.name ==== 'QUOTA_EXCEEDED_ERR' (Chrome) 或 'NS_ERROR_DOM_QUOTA_REACHED' (Firefox/Safari) 或 IE 中的 localStorage.remainingSpace === 0 时启动适当的清理操作。
【解决方案2】:

我会检查 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
}

【讨论】:

  • 在给定的情况下,这只是一个可以防止其他浏览器出错的功能......所以这并不能真正回答这个问题。如果关闭,localStorage 仍然在 window 中定义。
  • 你仍然得到一个 DOM 错误......我简直不敢相信没有办法检查它是否完全关闭......
  • 这对 Chrome 和 Opera 来说不是一种安全的方法...可能也不是 Safari,因为 localStorage 完全无法访问并且会引发异常。
  • 您不需要所有这些elses... 只需一个 try catch 就可以了。我看到你正在测试结果实际上是'yes',但我没有任何实际需要的用例。
【解决方案3】:

功能检测本地存储很棘手。你需要真正进入它。这样做的原因是 Safari 选择在私有模式下提供功能性 localStorage 对象,但它的配额设置为零。这意味着虽然所有简单的功能检测都会通过,但对localStorage.setItem 的任何调用都会引发异常。

Mozilla 在 Web Storage API 上的开发者网络条目有一个dedicated section on feature detecting local storage。这是该页面上推荐的方法:

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,你可以使用 storage-available 获取

npm install -S storage-available

然后像这样使用函数:

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

免责声明:MDN 上的文档部分和 NPM 包均由我撰写。

【讨论】:

  • 最佳答案,谢谢 Stijn。
【解决方案4】:

MDNupdated存储检测功能。 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,这仅意味着我们已经用完了所有可用的存储空间,但存储实际上是可用。我们的特征检测应该考虑到这些场景。

在此处查看brief history of feature-detecting localStorage。

【讨论】:

  • 这不是我在带有 iOS 12.1 的 Safari 中看到的确切行为。我可以设置并检索它们 - 在我关闭该选项卡后它们不会持续存在。即使我在同一选项卡中访问另一个网站并返回,我保存的数据仍然存在。所以不确定这条评论有多久了。
  • 显然这是一个已修复的错误 - stackoverflow.com/questions/14555347/…。必须假设您的用户是否处于私人模式,他们希望在离开并回来时失去“会话”。
  • 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 的行为:它会起作用,但前提是浏览器保持打开状态。
  • 在移动设备上使用 Safari 私有模式时尝试从本地存储写入或读取时没有收到任何错误。 Safari 将什么也不做,默默地失败。
【解决方案5】:

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

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

【讨论】:

    【解决方案6】:

    修改 Joe 的答案以添加 getter 使其更易于使用。用下面你简单地说: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 也不是更好......这个测试在你的代码中不会太频繁(如果你以一种聪明的方式编写它),那么为什么用一个非常短的变量来污染(全局)范围呢?
    • 你的权利。我必须解决这个问题...谢谢!
    • @StijndeWitt 现在可以使用了。感谢您的反馈...就污染全球范围而言,我理解您的观点,但我认为这是一种观点。有人可能会发现输入if(ls){... 是值得的。
    • ` === true` 不再需要检查函数结果而不是 getter 结果。键入lsTest() 比ls 更好,因为它更具描述性,而isLocalStorageAvailable() 会更好。最好避免使用 getter,因为它们可能会令人惊讶,因为没有迹象表明它会在键入(例如)ls 时执行代码。这里没有理由使用吸气剂。如果您真的不想要括号,您可以只计算一次可用性并将结果存储在全局变量中。然后考虑起来更简单(没有隐藏执行)并且整体更短。
    【解决方案7】:

    最好结合cookies检查localStorage的可用性,因为如果启用cookie,浏览器可以检测到localStorage可用并且type它是object,但不提供使用它的可能性。您使用下一个函数来检测localStorage 和cookies:

    const isLocalStorage = () => {
      try {
        if (typeof localStorage === 'object' && navigator.cookieEnabled) return true
        else return false
      } catch (e) {
        return false
      }
    }
    

    【讨论】:

    • 正如另一个答案中所解释的,这是一个 Safari 错误,它在隐私浏览时将 localStorage 设置为一个空对象。浏览器不应该这样做。 Cookies 和 localStorage 是完全不同的机制。
    • 这不是 Safari 错误。您可以在 Chrome 中查看,禁用 cookie 并重试
    【解决方案8】:

    这是一个简单的检查:

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

    【讨论】:

    • localStorage 的类型返回object,即使它在 Firefox 或 IE 中被禁用。在 Chrome 和 Opera 中,typeof 会在用户将其关闭时引发异常并破坏整个脚本...
    • 在 Safari 的隐私浏览模式下,您会得到一个有效的 localStorage 对象,其配额为零,因此每当您尝试写入它时都会引发异常。这就是为什么本地存储功能检测代码现在总是尝试写入项目。
    【解决方案9】:

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

        if( window.localStorage.fullName !== undefined){
    
               //action
       }else{
              }
    

    【讨论】:

    • 访问localStorage不需要等待文档加载完成(所以$()没有意义)更重要的是,如果localStorage不可用,这段代码会报错。
    • 实际上,Mozilla 文档声明 localStorage 本质上是同步的,因此它可以阻止主文档的呈现。因此,等待它准备好将是一个好方法。
    • 他们说localStorage 是同步的意思是localStorage.getItem('someKey') 实际上立即返回该项目。它不接受回调函数或返回Promise,它只是立即返回数据。将其与例如var result = fetch('https://example.com/data.json')... 返回一个 Promise,使其异步。您必须调用 then 方法来获取数据(只会在下一个刻度发生):result.then(function(data){ /* only here do we get the data */ })
    • 这是关于同步调用阻塞渲染的事实,中断了对页面的进一步解析。回调行为在这里无关紧要。
    猜你喜欢
    • 2021-02-11
    • 2020-03-21
    • 2018-05-30
    • 2017-12-26
    • 2018-02-15
    • 2017-09-19
    • 2013-04-07
    • 2013-03-05
    • 2018-09-09
    相关资源
    最近更新 更多