未捕获的InvalidStateError错误:在“IDBDatabase”上执行“transaction”失败:正在运行版本更改事务。

21

我必须承认我对indexedDB非常陌生。

我写了一段简单的indexedDB代码,如下所示:

i must admit that i am very new to indexedDB

I wrote a simple code of indexedDB and it is as followed:

function go() {
   var req = window.indexedDB.open("Uploader", 1),
      db;
   req.onerror = function (e) {
      console.log("Error");
   };
   req.onsuccess = function (e) {
      db = e.target.result;
   };
   req.onupgradeneeded = function (e) {
      console.log(db);
      db = e.target.result;
      var os = db.createObjectStore("Files", { keyPath: "files" });
      os.createIndex("text", "text_file", { unique: false });
      var trans = db.transaction(["text"], "readwrite");
      var objectstore = trans.objectStore("text");
      var addreq = objectstore.add("Instructions.js");
      addreq.onsuccess = function (e) {
         console.log("Success!");
         console.dir(e);
      };
   };
}

它给出的错误是Uncaught InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running.

它说正在运行一个版本更改事务A version change Transaction is running,但据我所学,版本更改事务是通过IDBFactory.open方法创建的,并且我没有使用它。我已经指定了这个事务是readwrite并且在onupgradeneeded中,那么为什么会出现错误呢?

我必须承认我对indexedDB非常陌生。

4个回答

19
版本更改事务还允许您进行读写操作。您只需要在onupgradeneeded函数中访问为您创建的事务即可。
var req = indexeddb.open(...);
req.onupgradeneeded = function(event) {
  // note that event.target === req === this, use whatever you like
  var db = event.target.result;

  // createObjectScore implicitly uses the versionchange txn running 
  // here, without telling you, basically a convenience function
  var objectStore = db.createObjectStore(...);

  // the important part that i am describing in this answer, 
  // grab the handle of the versionchange txn 
  // that is already running and was created for you
  // note again that event.target === req, you could just do
  // req.transaction or this.transaction here.
  // note this is a property of the open request, not a method.
  // do NOT confuse this with the method transaction() that is 
  // used to create a new transaction.
  var txn = event.target.transaction;

  // txn.objectStore(...) works here because the earlier
  // createObjectStore call guarantees the store exists
  // within the implicit upgrade txn
  var addRequest = txn.objectStore(...).add('value');

  // if in previous line we did:
  // var objectStoreRetrievedFromTxn = txn.objectStore(...);
  // then that variable is equal to the same variable returned from 
  // db.createObjectStore earlier in this function. Both are simply handles 
  // (references, pointers, whatever you want to call it) to the store.

 // silly example here if you want to known when the implicit txn 
 // completes. not very useful since success event will fire 
 // shorter after versionchange txn completes and you might as well
 // just wait for success
 addRequest.onsuccess = function() {console.log('Success!');};
};

// called once upgrade txn completes (if it even needed to run), 
// and db is opened
req.onsuccess = function(event) {
  console.log('upgrade txn completed and db is now connected');
  // here, create whatever readwrite or readonly txns you want, note these 
  // txns are separate from and different than the versionchange txn from 
  // before, because that is a unique transaction only available within 
  // onupgradeneeded. however, both versionchange and readwrite are similar
  // in that both support calls to put or add
};

您遇到此错误是因为在版本更改事务仍在运行时,您正在尝试启动第二个事务。


1
但是我如何指定交易的跨度? - anni saini
它给了我一个错误Uncaught NotFoundError: Failed to execute 'objectStore' on 'IDBTransaction': The specified object store was not found.在行transaction.objectStore('text') - anni saini
有趣的是,在 onupgradeneeded 回调函数中, db.transaction 不起作用,但 event.target.transaction 可以。 - oomer

14

在尝试加载对象存储之前,您需要检查版本更改事务的完成状态:

request.onupgradeneeded =
    function(event) {
        db = event.target.result;
        var store = db.createObjectStore('Files', {keyPath:"files"});
        var transaction = event.target.transaction;

        transaction.oncomplete =
            function(event) {    
                // Now store is available to be populated
            }
    }

1
在版本更改中,您无需为事务指定范围。这始终是所有当前对象存储。 transaction.objectStore('text') 在这里,您正在尝试使用索引名称打开对象存储,这不会起作用。如果要访问索引,则需要先转到对象存储。将数据添加到对象存储中。
function go(){var req = window.indexedDB.open("Uploader", 1), db;
req.onerror=function(e){console.log('Error')};
req.onsuccess = function(e){db=e.target.result;};
req.onupgradeneeded = function(e){
    console.log(db);
    db=e.target.result;
    var trans=e.target.transaction;
    var os = db.createObjectStore('Files', {keyPath:"files"});
        os.createIndex('text', 'text_file', {unique:false})
    var objectstore=  trans.objectStore("Files");
    var addreq = objectstore.add('Instructions.js');
        addreq.onsuccess = function(e)  {console.log('Success!');console.dir(e)}
}}

尝试一下这个。

0

始终使用官方IndexedDB规范。MDN上存在很多不准确的信息,特别是涉及类型时。

const request = indexedDB.open("library", 3);
request.onupgradeneeded = function(event) {
  const db = request.result;
  const transaction = request.transaction;
  if (event.oldVersion < 3) {
    const bookStore = transaction.objectStore("books");
    const yearIndex = bookStore.createIndex("by_year", "year");
  }
};

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