2017-03-09 41 views
1

在IndexedDB的onupgradeneeded()事件中,我试图更新对象存储中的每条记录。为了更新他们,我需要先瓶坯的异步操作,但这会导致升级交易变得无效,出现错误在升级事件中异步更新IndexedDB

Failed to execute 'update' on 'IDBCursor': The transaction is not active.

在后续代码我模拟的异步操作与setTimeout()

let openRequest = indexedDB.open('myDb', 1); 

openRequest.onupgradeneeded = function (versionEvent) { 
    let db = versionEvent.target['result']; 
    let upgradeTransaction = versionEvent.target['transaction']; 

    if(versionEvent.oldVersion < 1) { 
     let objStore = db.createObjectStore('sample'); 
     objStore.add('one', '1'); 
     objStore.add('two', '2'); 
    } 

    if(versionEvent.oldVersion >= 1) { 
     let getCursor = upgradeTransaction.objectStore('sample').openCursor(); 

     getCursor.onsuccess = (e) => { 
      let cursor = e.target['result']; 
      if (cursor) { 
      setTimeout(() => { 
       cursor.update(cursor.value + ' updated'); 
       cursor.continue(); 
      }) 
      } 
     } 
    } 
}; 

https://plnkr.co/edit/DIIzLduZT1dwOEHAdzSf?p=preview

如果你运行这个plunker它将初始化IndexedDB的。然后,如果将版本号增加到2并再次运行,则会出现错误。

如果我的更新依赖于异步操作,如何更新升级事件中的IndexedDB?

回答

2

你需要一种不同的方法。选项包括:

  • 立即更改模式,但推迟为后续事务添加新数据。
  • 在尝试执行升级之前获取数据。由于提取数据很慢,因此可能不合需要。
  • 仅在需要升级时才有条件地提取数据。

后者有两种方法。您可以在没有版本号的情况下执行open(),检查版本,然后在低于所需值时执行读取/升级。或者您可以在新版本中打开并在升级时需要中止升级(从请求中获取事务并调用abort()),然后获取数据并重新尝试升级。

+0

谢谢!我想我选择3并且调用'open()'没有版本号。 – rob