anni saini
anni saini

Reputation: 403

Uncaught InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running

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);
      };
   };
}

the error it is giving me is Uncaught InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running.

It is saying that A version change Transaction is running but as far as i have studied, a version change transaction is made from IDBFactory.open method and i haven't used and i have specified that this transaction is readwrite and this transaction is in onupgradeneeded then why there is an error?

i must admit that i am very new to indexedDB

Upvotes: 25

Views: 26273

Answers (4)

Josh
Josh

Reputation: 18690

The versionchange transaction also allows you to readwrite. You just need to access the transaction created for you within the onupgradeneeded function.

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
};

You are encountering the error because you are trying to start a second transaction while the version change transaction is still running.

Upvotes: 21

James Bond
James Bond

Reputation: 2986

Always use the official IndexedDB specification. MDN lies, there are a lot of inaccuracies, especially when it comes to types.

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");
  }
};

Upvotes: 3

Velojet
Velojet

Reputation: 948

You need to check for the completion of the version change transaction before attempting to load the object store:

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
            }
    }

Upvotes: 17

Kristof Degrave
Kristof Degrave

Reputation: 4180

in a version change you do not need to specify a scope for the transaction. This is always all the prenset object stores. transaction.objectStore('text') here you are trying to open an object store with the name of the index, this isn't going to work. You need to go to the objectstore first if you want to access the index.

Adding data needs to be done on the objectstore.

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)}
}}

Give this a try

Upvotes: 3

Related Questions