【问题标题】:localStorage unreliable in FirefoxFirefox 中的 localStorage 不可靠
【发布时间】:2012-11-30 21:24:34
【问题描述】:

我正在为我玩的纸牌游戏开发deck building application。我正在使用 localStorage 来保存和检索卡片组。它似乎在 Chrome 中运行良好,但在 Firefox 中运行不可靠。

在 FF 中,一开始似乎一切正常,套牌甚至在重新加载后仍然存在。但是,如果我添加第二个牌组并重新加载,它只会找到第一个牌组。如果我删除第一个牌组,它就找不到任何东西了。

所有本地存储交互都在 scripts/vault.js 中,我将在下面重现。我做错了吗?

vault = {};
vault.makeKey = function (s) {
    return "deck:" + s;
};
vault.friendlyName = function(s) {
    if (s.indexOf("deck:") === 0) {
        return s.substring(5);
    } else {
        return s;
    }
};
vault.store = function (deck, name) {
    if (!window.localStorage) {
        alert("This browser doesn't support local storage. You will be unable to save decks.");
        return;
    }
    var key = vault.makeKey(name);
    localStorage.setItem(key, deck.export());
};
vault.retrieve = function (key) {
    deck.import(localStorage[key]);
};
vault.getDecks = function () {
    var keys = Object.keys(localStorage),
        out = [],
        i,
        k,
        name = "";
    for (i = 0; i < keys.length; i++) {
        k = keys[i];
        name = vault.friendlyName(k);
        if (name !== k && localStorage[k]) {
            out.push({name: name, key: k});
        }
    }
    out.sort(function (a, b) {
        return a.name > b.name ? 1 : -1;
    });
    return out;
};
vault.deleteDeck = function (key) {
    localStorage.removeItem(key);
};

基本上,由于缺少更好的术语,localStorage 中的键似乎有时会被“冻结”; localStorage 在我操作它时会正常运行,但是一旦我刷新页面,它似乎就会恢复到它被冻结的任何状态。

【问题讨论】:

  • 你能做一个jsfiddle.net 演示吗?
  • 我在第一篇文章中发布了指向应用程序本身的链接。又来了:asmor.com/anr
  • 好吧,如果它在小提琴中,我可以使用代码并检查不同的东西。这不是必需的,但它会让我自己和其他一些人更有可能修补它,看看我们是否能弄明白。
  • 我只是想把它提炼成可以发布在 JSFiddle 上的东西,但是发生的事情太多了。特别是考虑到我看到的行为取决于做特定的事情然后重新加载页面......我只是认为它不适合这个。无论如何,谢谢,伙计。

标签: javascript firefox local-storage


【解决方案1】:

我曾多次遇到同样的问题,起初我没有注意到它无法读取 localStorage 的原因,但我想我找到了解决方案。

localStorage 操作都是同步的,不同的浏览器在处理它们方面有一定的怪癖。

在您的情况下,问题似乎是您试图在 DOM 准备好之前读取 localStorage。我用 Firebug 尝试过,我在 vault.js 文件的开头添加了一个断点并重新加载页面,当代码中断时,我检查 dom-tab 并找到 localStorage 属性,它就在那里 - 存储的完整列表价值观。当我删除断点并重新加载页面时,页面加载后它们都消失了。

这可能是 Firefox 或其他浏览器的错误,只是更快地初始化 localStorage。

因此,作为您的问题的解决方案:尝试在 DOM 准备好后从 localStorage 获取密钥。

【讨论】:

  • 谢谢。虽然您的建议似乎不是它的原因,但它确实让我走上了在下面找到一个 hacky 解决方案的轨道。我仍然想找到它不起作用的真正原因并让它正常工作。
  • 确实是一个很奇怪的bug。似乎如果您在加载页面之前暂停页面的加载,然后恢复,值就在那里,但是如果您让页面先加载,它们就消失了。就好像有什么东西在它准备好之前试图访问它,而浏览器无法初始化 localStorage。可能值得为 Mozilla 提交一个错误,但它很难重现。
  • 已经几天了,我没有看到任何关于此的活动,所以我将继续并将您标记为已接受的答案。感谢您帮助我走上正轨!
【解决方案2】:

虽然这是一篇旧帖子,但我认为我的发现可能会有所帮助。我也遇到了同样的问题,所以我浏览了这篇文章,尝试了这个,这就是我注意到的,在 Firefox 中,如果你在 window.load 之前尝试用 localstorage 做任何事情(甚至是 localStorage.getItem),它将删除所有内容它,你将一无所有。所以无论你想设置或获取什么,都在 window.load 之后执行。

类似的东西

$( window ).load(function() {
    //do whatever you want to do with localstorage
});

顺便说一句,在此之前我曾尝试在 document.ready 上对 localStorage 进行一些操作,但失败了。

【讨论】:

    【解决方案3】:

    在此处发布此内容以帮助可能正在经历我现在正在经历的任何人。

    如果使用 Firefox,刷新页面后,您需要关闭并重新打开开发工具才能看到新的 localStorage 项。

    当页面刷新时,显示之前的 localStorage 项目。如果您关闭并重新打开开发工具,您可以看到新设置。从那时起(直到下一次刷新)所做的任何更改都将实时更新。

    肯定是 Firefox 开发工具的错误。

    我在这里报告了这个错误:https://bugzilla.mozilla.org/show_bug.cgi?id=1706710

    // 5 分钟后编辑 我现在无法重现它。我不确定,但我认为这可能是由于 Firefox 更新所致。它在我完成编写错误报告时更新。我真的在 Firefox 87 中发现了一个在我更新前 10 分钟在 Firefox 88 中修复的错误吗?!!如果再次发生,将在这里报告。

    【讨论】:

      【解决方案4】:

      我认为 jylauril 走在正确的轨道上。

      我一直在玩延迟,并注意到一些奇怪的行为。

      据我所知,似乎如果您在所有 JavaScript 完成执行之前触摸 localStorage,包括 JS 执行 setTimeout,localStorage 对于该网页浏览将显示为空白。例如:

      $(window).load(function () {
          console.log("Waiting 10000ms", new Date());
          setTimeout(setDeckSelect, 10000);
      });
      

      Firebug 的控制台:

      Waiting 10000ms Date {Thu Dec 13 2012 10:35:48 GMT-0500 (Eastern Standard Time)}
      exec.js (line 191)
      getDecks Date {Thu Dec 13 2012 10:35:58 GMT-0500 (Eastern Standard Time)}
      vault.js (line 23)
      >>> localStorage
      0 items in Storage 
      

      我以为我可能正在做某事,但到目前为止我的理论已被证明是错误的。不过,我注意到了一件奇怪的事情。不管我等待多长时间,如果我先尝试查找套牌,它将失败并且本地存储将是空的:

      >>> vault.getDecks()
      []
      >>> localStorage
      0 items in Storage 
      

      但是如果我按照相反的顺序做这些......

      >>> localStorage
      8 items in Storage deck:dfs=
      "{"identity":"MakingNews","cards":{}}", deck:ngrngfrn= "{"identity":"BuildingaBetterWorld","cards":{}}", deck:sdfgshsh= "{"identity":"MakingNews","cards":{}}", deck:sdfgdgdfg= "{"identity":"MakingNews","cards":{}}", deck:dfgdfgas= "{"identity":"EngineeringtheFuture","cards":{}}", deck:sdfsga= "{"identity":"MakingNews","cards":{}}", deck:gdgd= "{"identity":"MakingNews","cards":{}}", deck:gfsdfgsdfg= "{"identity":"BuildingaBetterWorld","cards":{}}"
      >>> vault.getDecks()
      [Object { name= "dfgdfgas",  key= "deck:dfgdfgas"}, Object { name= "dfs",  key= "deck:dfs"}, Object { name= "gdgd",  key= "deck:gdgd"}, Object { name= "gfsdfgsdfg",  key= "deck:gfsdfgsdfg"}, Object { name= "ngrngfrn",  key= "deck:ngrngfrn"}, Object { name= "sdfgdgdfg",  key= "deck:sdfgdgdfg"}, Object { name= "sdfgshsh",  key= "deck:sdfgshsh"}, Object { name= "sdfsga",  key= "deck:sdfsga"}]
      

      如果我在函数中记录 localStorage,它也可以工作:

      vault.getDecks = function () {
          console.log(localStorage);
          var keys = Object.keys(localStorage),
              out = [],
              i,
              k,
              name = "";
          for (i = 0; i < keys.length; i++) {
              k = keys[i];
              name = vault.friendlyName(k);
              if (name !== k && localStorage[k]) {
                  out.push({name: name, key: k});
              }
          }
          out.sort(function (a, b) {
              return a.name > b.name ? 1 : -1;
          });
          return out;
      };
      

      它有效。不过,如果我取消它...

      vault.getDecks = function () {
          // console.log(localStorage);
          void localStorage;
          var keys = Object.keys(localStorage),
              out = [],
              i,
              k,
              name = "";
          for (i = 0; i < keys.length; i++) {
              k = keys[i];
              name = vault.friendlyName(k);
              if (name !== k && localStorage[k]) {
                  out.push({name: name, key: k});
              }
          }
          out.sort(function (a, b) {
              return a.name > b.name ? 1 : -1;
          });
          return out;
      };
      

      它不起作用。如果我删除 void 关键字并仅使用 localStorage 作为语句,它也不起作用。

      我不知道为什么,但是 console.log(localstorage) 似乎可以解决这个问题,我可以随时调用 localStorage。

      真的很奇怪。

      编辑:我找到了一个稍微好一点的解决方案。调用 localStorage 的 'length' 属性也可以。

      vault.getDecks = function () {
          //Weird hack to make FF load localStorage correctly...
          localStorage.length;
          var keys = Object.keys(localStorage),
              out = [],
              i,
              k,
              name = "";
          for (i = 0; i < keys.length; i++) {
              k = keys[i];
              name = vault.friendlyName(k);
              if (name !== k && localStorage[k]) {
                  out.push({name: name, key: k});
              }
          }
          out.sort(function (a, b) {
              return a.name > b.name ? 1 : -1;
          });
          return out;
      };
      

      这更好一点,因为它不记录任何内容...

      【讨论】:

      • 虽然这似乎确实有效,但我将这个问题悬而未决,希望有人可以解释这个问题和/或提供一个不是丑陋的黑客的解决方案。
      【解决方案5】:

      • 确保 localStorage 数据在所有 html 页面中始终可用: o 域(本地上下文)必须相同。 o 确保在所有 Html 文件中保持 > 标签相同, o(仅限 Firefox)确保所有 JavaScript 文件中的 onPageLoad 保持相同(添加到 html 文件中),即确保向 PageLoadEvent 添加相同的函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多