当您在 Chrome 上删除数据库时,indexedDB 不会重置版本 - 错误或用户错误?

Jos*_*man 4 javascript firefox google-chrome indexeddb

如果我设置buggytrue.

由于我对 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>
Run Code Online (Sandbox Code Playgroud)

在 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
Run Code Online (Sandbox Code Playgroud)

在 Firefox 中它工作得很好。

顺便说一句,在 Chrome 和 Firefox 中,它的运行速度非常慢——比如单次创建和删除数据库需要 5-10 秒。这是正常/预期的吗?难道我做错了什么?

pal*_*ind 5

这是一个用户错误。

在 Firefox 和 Chrome 中 IndexedDB 的删除速度都非常快。我没有做过任何测量。但客观来看:在SyncedDB的测试套件中,我在每个测试之间删除并创建了一个数据库。目前有 67 个测试,执行时间不到一秒。而且数据库的删除和创建绝对不是测试中最耗时的部分。

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

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

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

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
    }
};
Run Code Online (Sandbox Code Playgroud)

插入这个你会发现 Firefox 和 Chrome 都不会非常快速地创建和删除数据库tests