如何向现有的indexeddb添加新的Objectstore

6

请问有谁能告诉我如何在已经有版本号的indexeddb实例中添加一个新的对象存储。当我尝试创建一个新版本时,现有的对象存储会被删除。

我的版本号是'1',其中包含大约10个带有数据的对象存储。当我尝试使用新的版本号打开同一数据库时,我丢失了当前的数据和对象存储。

以下是我尝试过的方法。

var _upRequest = indexedDB.open("employees");

    _upRequest.onsuccess = function (e) {
        var thisDb = e.target.result;
        var version = parseInt(thisDb.version)+1;
        thisDb.close();
        var openRequest = indexedDB.open("employees", version);

        //handle setup, this will be run by Firefox
        openRequest.onupgradeneeded = function (e) {
            console.log("running onupgradeneeded");
            var thisDb = e.target.result;

            //Create Employee
            if (!thisDb.objectStoreNames.contains("employee")) {
                console.log("I need to make the employee objectstore");
                var objectStore = thisDb.createObjectStore("employee", { keyPath: "id", autoIncrement: true });
                objectStore.createIndex("searchkey", "searchkey", { unique: false });
            }
            thisDb.close();
        }

        openRequest.onsuccess = function (e) {

            db = e.target.result;

            db.onerror = function (e) {
                alert("Sorry, an unforseen error was thrown.");
                console.log("***ERROR***");
                console.dir(e.target);
            }

            db.close();
        }
    }

你为什么要使用 setVersion?它不是已经被弃用了吗?你使用了哪些资源来建议使用 setVersion? - Josh
@Josh 这是我从另一个链接中引用的代码参考。它对我来说不起作用。所以我已经从这里删除并更新了问题。 - Pradeep
2个回答

8

我没有直接的答案,但你当前编写的代码似乎有些奇怪。

首先要尝试的一件事是正确地绑定onupgradeneeded、onerror,并且不要过早关闭数据库。

不要这样做:

var request = indexedDB.open();
request.onsuccess = function() {
  request.onupgradeneeded = function() {};
};

请改为以下方式:
var request = indexedDB.open();
request.onsuccess = function() {};
request.onupgradeneeded = function() {};

同样地,立即绑定onerror事件,而不是在onupgradeneeded或onsuccess中稍后再绑定,像这样:

var request = indexedDB.open();
request.onsuccess = function() {};
request.onupgradeneeded = function() {};
request.onerror = function() {};

当indexedDB.open检测到更高版本或第一个版本时,它将分派一个upgradeneeded事件,等待暗示的“versionchange”事务完成,然后分派一个success事件。
我无法完全理解你的代码。我不确定为什么你要打开一个连接,关闭它,然后打开第二个连接,然后延迟绑定upgradeneeded处理程序。
这是添加对象存储并访问它所需做的全部内容:
var request = indexedDB.open('name', aNumberGreaterThanTheCurrentVersion);
request.onupgradeneeded = function(event) {
  console.log('Performing upgrade');
  var db = event.target.result;
  console.log('Creating object store');
  db.createObjectStore('mystore');
};

request.onsuccess = function(event) {
  console.log('Connected to database');
  var db = event.target.result;
  var tx = db.transaction('mystore');
  var store = tx.objectStore('mystore');
  console.log('Doing something with store "mystore"');
  // ...
  console.log('Finished doing something, now closing');
  db.close();
};

request.onerror = console.error;

另外需要注意的是,indexedDB会产生不同类型的错误,因此区分它们非常重要。与您的日志消息所示不同,request.onerror并没有“抛出”异常。相反,发生了indexedDB分派错误事件的情况。分派的错误事件没有被“抛出”。现在,除此之外,indexedDB的几个函数可能会抛出异常。这些需要通过try/catch块来捕获。您甚至看不到分派的错误事件。您将获得一个实际的脚本错误,它会停止执行并自动显示在控制台中,并提供稍微有用的消息。


@Josh- 我的需求是在我的应用程序(Angularjs SPA)加载时创建一组表。在加载另一个视图或屏幕时,我正在尝试向已经有一些表的现有数据库中添加一个对象存储。根据我的理解,为了添加一个新的对象存储,我需要增加现有数据库的版本号,并在onupgradeneeded函数中添加对象存储。 - Pradeep
您提供的解决方案在仅使用HTML+JavaScript时运行良好,但在使用HTML+JavaScript+AngularJS时却无法正常工作。 - Pradeep
那么这可能是与Angular或您对Angular的使用有关的问题。我建议您使用适当的Angular标签进行标记,并希望Angular团队能够帮助您。在提问之前,我建议您清理和澄清代码,因为您可能不会收到有用的回复。 - Josh
1
还有一个问题。当我使用更新版本打开数据库时,它不会触发onupgradeneeded事件,但会触发onblocked事件。在这种情况下,我该如何添加新的对象存储? - Pradeep
非常晚了,我随机地注意到这一点,但是upgradeneeded是通过在具有更高版本号的数据库上调用indexedDB.open来触发的。 - Josh

1
let OpenReq = indexedDB.open( 'dbName', version );
OpenReq.onupgradeneeded = function( e )
{
    let db = e.target.result;
    db.objectStoreNames.contains( "myStore" ) || db.createObjectStore( "myStore" );
}

如果您已经有一个版本为1的现有数据库,使用version = 2运行上述代码将保留现有存储。

另一种方法是检查旧版本:if (event.oldVersion < 1) { db.createObjectStore('myStore') } - piotr_cz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接