删除Chrome上的数据库时,indexedDB没有重置版本 - 错误或用户错误?

时间:2014-06-08 21:29:34

标签: javascript google-chrome firefox indexeddb

如果我将buggy设置为true,则以下代码会在Chrome 35(但不是Firefox 29)中引发错误。

因为我在indexedDB中很新,所以我想问一下这是否应该有效。如果我删除了数据库并使用version=1再次打开它,那么我的onupgradeneeded回调是否应该被调用?

<html>
  <head>
    <script type="text/javascript">
      var i = 1000;
      var buggy = true;
      function open() {
        var version = buggy ? 1 : 1001 - i;
        var request = indexedDB.open("test", version);
        var upgraded = false;
        request.onupgradeneeded = function() {
          upgraded = true;
          console.log("upgraded ok");
        }
        request.onsuccess = function() {
          if (!upgraded) {
            throw "Not upgraded";
          }
          console.log("open ok");
          if (--i != 0) { obliterate(); }
        }
        request.onerror = function() {
          throw "Error in open";
        }
      }

      function obliterate() {
        var request = indexedDB.deleteDatabase("test");
        request.onsuccess = function() {
          console.log("delete ok");
          open();
        }
        request.onerror = function(event) {
          throw "Error in obliterate.";
        }
      }

      obliterate();
    </script>
  </head>
  <body>
  </body>
</html>

在Chrome中,使用buggy=true,我得到:

delete ok test.html:29
upgraded ok test.html:12
open ok test.html:18
delete ok test.html:29
Uncaught Not upgraded

在Firefox中它可以正常工作。

作为旁注,在Chrome和Firefox中,这都非常缓慢 - 比如一次创建和删除数据库需要5-10秒。这是正常/预期的吗?我做错了吗?

1 个答案:

答案 0 :(得分:2)

这是用户错误。

在Firefox和Chrome中,IndexedDB中的删除速度非常快。我还没有做过任何测量。但是要深思熟虑:在SyncedDB的测试套件中,我删除并在每个测试之间创建一个数据库。目前有67项测试,它们在不到一秒的时间内完成。数据库删除和创建绝对不是测试中最耗时的部分。

你偶然发现的是IndexedDB如何工作的棘手部分之一。 IndexedDB具有数据库连接的概念。与您的问题相关的部分是:

  • 通过使用open函数打开数据库来建立连接。连接由您通过open获取的IDBDatabase表示。
  • 只要数据库是打开的连接,就无法删除数据库。
  • 尝试删除数据库时,会针对连接到数据库的所有打开的IDBDatabase对象触发“versionchange”事件。该活动的newVersion属性设置为null

问题是您在obliterate请求open事件处理程序中调用了onsuccess函数。在这一点上,您正在尝试删除具有开放连接的数据库。这是有问题的,这就是为什么你的示例代码在Chrome中不起作用(看起来Firefox超时连接并完成删除,尽管有很大的延迟)。

修复方法是在versionchange事件处理程序中附加onsuccess事件的侦听器。在if (--i != 0) { obliterate(); }行之后添加此内容:

request.result.onversionchange = function(e) {
    if (e.newVersion === null) { // An attempt is made to delete the db
        e.target.close(); // Manually close our connection to the db
    }
};

插入此页后,您会发现Firefox和Chrome都无法快速创建和删除tests数据库。