检查 localStorage 是不是可用

Posted

技术标签:

【中文标题】检查 localStorage 是不是可用【英文标题】: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!');
  

【问题讨论】:

仍然没有提供任何方法来查看它是否工作...... 嗯嗯嗯。如果它抛出一个异常你知道它不工作 How to detect if browser supports html5 Local Storage的可能重复 Check for HTML 5 localStorage的可能重复 【参考方案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 中看到的确切行为。我可以设置并检索它们 - 在我关闭该选项卡后它们不会持续存在。即使我在同一选项卡中访问另一个网站并返回,我保存的数据仍然存在。所以不确定这条评论有多久了。 显然这是一个已修复的错误 - ***.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,但不提供使用它的可能性。您使用下一个函数来检测localStoragecookies

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 */ ) 这是关于同步调用阻塞渲染的事实,中断了对页面的进一步解析。回调行为在这里无关紧要。

以上是关于检查 localStorage 是不是可用的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 React PWA 是不是使用最新版本?

检查用户是不是已存在于 localStorage

HTML5 LocalStorage:检查密钥是不是存在[重复]

创建用于检查 LocalStorage 是不是为空的全局函数 - Vue.JS

localStorage和sessionStorage

useEffect 不监听 localStorage